From 464422e7d474a8e37c13d37df6981e7f22949aa4 Mon Sep 17 00:00:00 2001 From: Grazcoin Date: Sun, 2 Mar 2014 11:10:12 +0100 Subject: [PATCH 1/4] remove user interface and leave json only parsing keep json branch without user-interface on top of DEx code base --- msc_compare.py | 99 - msc_compare_cron.sh | 18 - msc_cron.sh | 25 +- msc_prices.py | 68 - www/404.html | 110 - www/API.html | 111 - www/About.html | 115 - www/Address.html | 440 - www/License.html | 111 - www/Search.html | 15 - www/acceptform.html | 268 - www/acceptform.js | 652 - www/addr/.gitignore | 2 - www/address.js | 121 - www/btc02.js | 290 - www/btcpayment.html | 187 - www/btcpayment.js | 52 - www/btcutils.js | 37 - www/css/acceptform.css | 179 - www/css/bootstrap-combobox.css | 150 - www/css/bootstrap-theme.css | 405 - www/css/bootstrap.css | 6805 -------- www/css/bootstrap.min.css | 9 - www/css/search.css | 73 - www/exodus.html | 194 - www/fonts/glyphicons-halflings-regular.eot | Bin 14079 -> 0 bytes www/fonts/glyphicons-halflings-regular.svg | 228 - www/fonts/glyphicons-halflings-regular.ttf | Bin 29512 -> 0 bytes www/fonts/glyphicons-halflings-regular.woff | Bin 16448 -> 0 bytes www/general/.gitignore | 2 - www/ico/apple-touch-icon-114-precomposed.png | Bin 2939 -> 0 bytes www/ico/apple-touch-icon-144-precomposed.png | Bin 3614 -> 0 bytes www/ico/apple-touch-icon-57-precomposed.png | Bin 1577 -> 0 bytes www/ico/apple-touch-icon-72-precomposed.png | Bin 1932 -> 0 bytes www/ico/bitcoin.png | Bin 1435 -> 0 bytes www/ico/bitcoin24b.png | Bin 4050 -> 0 bytes www/ico/bitcoin24t.png | Bin 3228 -> 0 bytes www/ico/bitcoin32b.png | Bin 4507 -> 0 bytes www/ico/bitcoin32t.png | Bin 3383 -> 0 bytes www/ico/bitcoin48b.png | Bin 5446 -> 0 bytes www/ico/bitcoin48t.png | Bin 3615 -> 0 bytes www/ico/coins24b.png | Bin 4153 -> 0 bytes www/ico/coins24t.png | Bin 3312 -> 0 bytes www/ico/coins32b.png | Bin 4812 -> 0 bytes www/ico/coins32t.png | Bin 3601 -> 0 bytes www/ico/coins48b.png | Bin 6303 -> 0 bytes www/ico/coins48t.png | Bin 4035 -> 0 bytes www/ico/exodus.png | Bin 1313 -> 0 bytes www/ico/exodus24b.png | Bin 4036 -> 0 bytes www/ico/exodus24t.png | Bin 403 -> 0 bytes www/ico/exodus24t_.png | Bin 3247 -> 0 bytes www/ico/exodus32b.png | Bin 4367 -> 0 bytes www/ico/exodus32t.png | Bin 3329 -> 0 bytes www/ico/exodus48b.png | Bin 5114 -> 0 bytes www/ico/exodus48t.png | Bin 3511 -> 0 bytes www/ico/favicon.png | Bin 889 -> 0 bytes www/ico/sellaccept.png | Bin 705 -> 0 bytes www/ico/sellaccept24b.png | Bin 4328 -> 0 bytes www/ico/sellaccept24t.png | Bin 3352 -> 0 bytes www/ico/sellaccept32b.png | Bin 4957 -> 0 bytes www/ico/sellaccept32t.png | Bin 3529 -> 0 bytes www/ico/sellaccept48.png | Bin 3741 -> 0 bytes www/ico/sellaccept48b.png | Bin 6485 -> 0 bytes www/ico/sellaccept48t.png | Bin 3913 -> 0 bytes www/ico/selloffer.png | Bin 1725 -> 0 bytes www/ico/selloffer24b.png | Bin 928 -> 0 bytes www/ico/selloffer24b_.png | Bin 3965 -> 0 bytes www/ico/selloffer24t.png | Bin 349 -> 0 bytes www/ico/selloffer24t_.png | Bin 3183 -> 0 bytes www/ico/selloffer32b.png | Bin 4380 -> 0 bytes www/ico/selloffer32t.png | Bin 403 -> 0 bytes www/ico/selloffer48b.png | Bin 5217 -> 0 bytes www/ico/selloffer48t.png | Bin 3532 -> 0 bytes www/ico/simplesend.png | Bin 3033 -> 0 bytes www/ico/simplesend24b.png | Bin 990 -> 0 bytes www/ico/simplesend24b_.png | Bin 3813 -> 0 bytes www/ico/simplesend24t.png | Bin 387 -> 0 bytes www/ico/simplesend24t_.png | Bin 3033 -> 0 bytes www/ico/simplesend32b.png | Bin 4011 -> 0 bytes www/ico/simplesend32t.png | Bin 3117 -> 0 bytes www/ico/simplesend48b.png | Bin 4759 -> 0 bytes www/ico/simplesend48t.png | Bin 3230 -> 0 bytes www/ico/undefined.png | Bin 4079 -> 0 bytes www/ico/undefined24t.png | Bin 3249 -> 0 bytes www/ico/undefined32b.png | Bin 4543 -> 0 bytes www/ico/undefined32t.png | Bin 3386 -> 0 bytes www/ico/undefined48b.png | Bin 5659 -> 0 bytes www/ico/undefined48t.png | Bin 3675 -> 0 bytes www/img/Thumbs.db | Bin 6656 -> 0 bytes www/img/about.png | Bin 3261 -> 0 bytes www/img/add.png | Bin 2168 -> 0 bytes www/img/ajax_loader.gif | Bin 19110 -> 0 bytes www/img/alert-overlay.png | Bin 135 -> 0 bytes www/img/alert.png | Bin 2307 -> 0 bytes www/img/downIcon.png | Bin 2145 -> 0 bytes www/img/download.png | Bin 2938 -> 0 bytes www/img/flatIcon.png | Bin 1906 -> 0 bytes www/img/license.png | Bin 2271 -> 0 bytes www/img/logo.png | Bin 15752 -> 0 bytes www/img/logo_28.png | Bin 7881 -> 0 bytes www/img/masterchain_icon_48x48.png | Bin 3420 -> 0 bytes www/img/masterchain_icon_64x64.png | Bin 5024 -> 0 bytes www/img/masterchain_logo_48.png | Bin 15752 -> 0 bytes www/img/masterchain_logo_64.png | Bin 21221 -> 0 bytes www/img/remove.png | Bin 2031 -> 0 bytes www/img/upIcon.png | Bin 2218 -> 0 bytes www/index.html | 186 - www/javascript_required.html | 57 - www/js/BTCClientContext.js | 242 - www/js/BitcoinJS/address.js | 57 - www/js/BitcoinJS/base58.js | 71 - www/js/BitcoinJS/bitcoin.js | 175 - www/js/BitcoinJS/crypto-js/crypto-min.js | 7 - www/js/BitcoinJS/crypto-js/crypto.js | 160 - www/js/BitcoinJS/crypto-js/ripemd160.js | 170 - www/js/BitcoinJS/crypto-js/sha256-min.js | 7 - www/js/BitcoinJS/crypto-js/sha256.js | 133 - www/js/BitcoinJS/ecdsa.js | 475 - www/js/BitcoinJS/eckey.js | 131 - www/js/BitcoinJS/events/eventemitter.js | 98 - www/js/BitcoinJS/exit/client.js | 148 - www/js/BitcoinJS/jsbn/ec.js | 316 - www/js/BitcoinJS/jsbn/jsbn.js | 559 - www/js/BitcoinJS/jsbn/jsbn2.js | 656 - www/js/BitcoinJS/jsbn/prng4.js | 45 - www/js/BitcoinJS/jsbn/rng.js | 68 - www/js/BitcoinJS/jsbn/sec.js | 173 - www/js/BitcoinJS/message.js | 69 - www/js/BitcoinJS/opcode.js | 154 - www/js/BitcoinJS/paillier.js | 118 - www/js/BitcoinJS/script.js | 347 - www/js/BitcoinJS/transaction.js | 445 - www/js/BitcoinJS/txdb.js | 62 - www/js/BitcoinJS/util.js | 228 - www/js/BitcoinJS/wallet.js | 308 - www/js/angular.js | 14847 ----------------- www/js/bootstrap-combobox.js | 429 - www/js/bootstrap.js | 1999 --- www/js/bootstrap.min.js | 6 - www/js/html5shiv.js | 8 - www/js/htmlpost.xml | 33 - www/js/jquery-1.10.1.min.js | 6 - www/js/jquery.json-2.4.js | 199 - www/js/jquery.qrcode.min.js | 28 - www/js/respond.min.js | 6 - www/js/truncate.js | 68 - www/js/tx.js | 507 - www/masterEvents.js | 6 - www/masterPage.js | 58 - www/offlinesign.html | 176 - www/offlinesign.js | 202 - www/professional.html | 113 - www/redirect.js | 61 - www/sellaccept.html | 239 - www/sellaccept.js | 55 - www/sellform.html | 282 - www/sellform.js | 636 - www/selloffer.html | 276 - www/selloffer.js | 54 - www/sendform.html | 300 - www/sendform.js | 632 - www/sendjson.html | 79 - www/sendjson.js | 24 - www/simplesend.html | 194 - www/simplesend.js | 46 - www/wallet.html | 152 - www/wallet.js | 357 - 167 files changed, 2 insertions(+), 38507 deletions(-) delete mode 100644 msc_compare.py delete mode 100644 msc_compare_cron.sh delete mode 100644 msc_prices.py delete mode 100644 www/404.html delete mode 100644 www/API.html delete mode 100644 www/About.html delete mode 100644 www/Address.html delete mode 100644 www/License.html delete mode 100644 www/Search.html delete mode 100644 www/acceptform.html delete mode 100644 www/acceptform.js delete mode 100644 www/addr/.gitignore delete mode 100644 www/address.js delete mode 100644 www/btc02.js delete mode 100644 www/btcpayment.html delete mode 100644 www/btcpayment.js delete mode 100644 www/btcutils.js delete mode 100644 www/css/acceptform.css delete mode 100644 www/css/bootstrap-combobox.css delete mode 100644 www/css/bootstrap-theme.css delete mode 100644 www/css/bootstrap.css delete mode 100644 www/css/bootstrap.min.css delete mode 100644 www/css/search.css delete mode 100644 www/exodus.html delete mode 100644 www/fonts/glyphicons-halflings-regular.eot delete mode 100644 www/fonts/glyphicons-halflings-regular.svg delete mode 100644 www/fonts/glyphicons-halflings-regular.ttf delete mode 100644 www/fonts/glyphicons-halflings-regular.woff delete mode 100644 www/general/.gitignore delete mode 100644 www/ico/apple-touch-icon-114-precomposed.png delete mode 100644 www/ico/apple-touch-icon-144-precomposed.png delete mode 100644 www/ico/apple-touch-icon-57-precomposed.png delete mode 100644 www/ico/apple-touch-icon-72-precomposed.png delete mode 100644 www/ico/bitcoin.png delete mode 100644 www/ico/bitcoin24b.png delete mode 100644 www/ico/bitcoin24t.png delete mode 100644 www/ico/bitcoin32b.png delete mode 100644 www/ico/bitcoin32t.png delete mode 100644 www/ico/bitcoin48b.png delete mode 100644 www/ico/bitcoin48t.png delete mode 100644 www/ico/coins24b.png delete mode 100644 www/ico/coins24t.png delete mode 100644 www/ico/coins32b.png delete mode 100644 www/ico/coins32t.png delete mode 100644 www/ico/coins48b.png delete mode 100644 www/ico/coins48t.png delete mode 100644 www/ico/exodus.png delete mode 100644 www/ico/exodus24b.png delete mode 100644 www/ico/exodus24t.png delete mode 100644 www/ico/exodus24t_.png delete mode 100644 www/ico/exodus32b.png delete mode 100644 www/ico/exodus32t.png delete mode 100644 www/ico/exodus48b.png delete mode 100644 www/ico/exodus48t.png delete mode 100644 www/ico/favicon.png delete mode 100644 www/ico/sellaccept.png delete mode 100644 www/ico/sellaccept24b.png delete mode 100644 www/ico/sellaccept24t.png delete mode 100644 www/ico/sellaccept32b.png delete mode 100644 www/ico/sellaccept32t.png delete mode 100644 www/ico/sellaccept48.png delete mode 100644 www/ico/sellaccept48b.png delete mode 100644 www/ico/sellaccept48t.png delete mode 100644 www/ico/selloffer.png delete mode 100644 www/ico/selloffer24b.png delete mode 100644 www/ico/selloffer24b_.png delete mode 100644 www/ico/selloffer24t.png delete mode 100644 www/ico/selloffer24t_.png delete mode 100644 www/ico/selloffer32b.png delete mode 100644 www/ico/selloffer32t.png delete mode 100644 www/ico/selloffer48b.png delete mode 100644 www/ico/selloffer48t.png delete mode 100644 www/ico/simplesend.png delete mode 100644 www/ico/simplesend24b.png delete mode 100644 www/ico/simplesend24b_.png delete mode 100644 www/ico/simplesend24t.png delete mode 100644 www/ico/simplesend24t_.png delete mode 100644 www/ico/simplesend32b.png delete mode 100644 www/ico/simplesend32t.png delete mode 100644 www/ico/simplesend48b.png delete mode 100644 www/ico/simplesend48t.png delete mode 100644 www/ico/undefined.png delete mode 100644 www/ico/undefined24t.png delete mode 100644 www/ico/undefined32b.png delete mode 100644 www/ico/undefined32t.png delete mode 100644 www/ico/undefined48b.png delete mode 100644 www/ico/undefined48t.png delete mode 100644 www/img/Thumbs.db delete mode 100644 www/img/about.png delete mode 100644 www/img/add.png delete mode 100644 www/img/ajax_loader.gif delete mode 100644 www/img/alert-overlay.png delete mode 100644 www/img/alert.png delete mode 100644 www/img/downIcon.png delete mode 100644 www/img/download.png delete mode 100644 www/img/flatIcon.png delete mode 100644 www/img/license.png delete mode 100644 www/img/logo.png delete mode 100644 www/img/logo_28.png delete mode 100644 www/img/masterchain_icon_48x48.png delete mode 100644 www/img/masterchain_icon_64x64.png delete mode 100644 www/img/masterchain_logo_48.png delete mode 100644 www/img/masterchain_logo_64.png delete mode 100644 www/img/remove.png delete mode 100644 www/img/upIcon.png delete mode 100644 www/index.html delete mode 100644 www/javascript_required.html delete mode 100644 www/js/BTCClientContext.js delete mode 100644 www/js/BitcoinJS/address.js delete mode 100644 www/js/BitcoinJS/base58.js delete mode 100644 www/js/BitcoinJS/bitcoin.js delete mode 100644 www/js/BitcoinJS/crypto-js/crypto-min.js delete mode 100644 www/js/BitcoinJS/crypto-js/crypto.js delete mode 100644 www/js/BitcoinJS/crypto-js/ripemd160.js delete mode 100644 www/js/BitcoinJS/crypto-js/sha256-min.js delete mode 100644 www/js/BitcoinJS/crypto-js/sha256.js delete mode 100644 www/js/BitcoinJS/ecdsa.js delete mode 100644 www/js/BitcoinJS/eckey.js delete mode 100644 www/js/BitcoinJS/events/eventemitter.js delete mode 100644 www/js/BitcoinJS/exit/client.js delete mode 100644 www/js/BitcoinJS/jsbn/ec.js delete mode 100644 www/js/BitcoinJS/jsbn/jsbn.js delete mode 100644 www/js/BitcoinJS/jsbn/jsbn2.js delete mode 100644 www/js/BitcoinJS/jsbn/prng4.js delete mode 100644 www/js/BitcoinJS/jsbn/rng.js delete mode 100644 www/js/BitcoinJS/jsbn/sec.js delete mode 100644 www/js/BitcoinJS/message.js delete mode 100644 www/js/BitcoinJS/opcode.js delete mode 100644 www/js/BitcoinJS/paillier.js delete mode 100644 www/js/BitcoinJS/script.js delete mode 100644 www/js/BitcoinJS/transaction.js delete mode 100644 www/js/BitcoinJS/txdb.js delete mode 100644 www/js/BitcoinJS/util.js delete mode 100644 www/js/BitcoinJS/wallet.js delete mode 100644 www/js/angular.js delete mode 100644 www/js/bootstrap-combobox.js delete mode 100644 www/js/bootstrap.js delete mode 100644 www/js/bootstrap.min.js delete mode 100644 www/js/html5shiv.js delete mode 100644 www/js/htmlpost.xml delete mode 100644 www/js/jquery-1.10.1.min.js delete mode 100644 www/js/jquery.json-2.4.js delete mode 100644 www/js/jquery.qrcode.min.js delete mode 100644 www/js/respond.min.js delete mode 100644 www/js/truncate.js delete mode 100644 www/js/tx.js delete mode 100644 www/masterEvents.js delete mode 100644 www/masterPage.js delete mode 100644 www/offlinesign.html delete mode 100644 www/offlinesign.js delete mode 100644 www/professional.html delete mode 100644 www/redirect.js delete mode 100644 www/sellaccept.html delete mode 100644 www/sellaccept.js delete mode 100644 www/sellform.html delete mode 100644 www/sellform.js delete mode 100644 www/selloffer.html delete mode 100644 www/selloffer.js delete mode 100644 www/sendform.html delete mode 100644 www/sendform.js delete mode 100644 www/sendjson.html delete mode 100644 www/sendjson.js delete mode 100644 www/simplesend.html delete mode 100644 www/simplesend.js delete mode 100644 www/wallet.html delete mode 100644 www/wallet.js diff --git a/msc_compare.py b/msc_compare.py deleted file mode 100644 index 03c1e36..0000000 --- a/msc_compare.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python -import os -import urllib2 -from optparse import OptionParser -from msc_utils_validating import * - -# get domain name from url -def url_to_domain(u): - return u.split('//')[1].split('.')[0] - -################################################################# -# main function - compares mastercoin_verify of implementations # -################################################################# -def compare(): - - # parse command line arguments - parser = OptionParser("usage: %prog [options]") - parser.add_option("-d", "--debug", action="store_true",dest='debug_mode', default=False, - help="turn debug mode on") - - (options, args) = parser.parse_args() - msc_globals.init() - msc_globals.d=options.debug_mode - - info('starting comparison') - - difference_dict={} - - urls_list_dict={'MSC': \ - ['https://masterchain.info/mastercoin_verify/addresses/0', \ - 'https://masterchest.info/mastercoin_verify/addresses.aspx', \ - 'http://mymastercoins.com/jaddress.aspx?currency_id=1'], \ - 'TMSC': \ - ['https://masterchain.info/mastercoin_verify/addresses/1', \ - 'https://masterchest.info/mastercoin_verify/addresses_test.aspx', \ - 'http://mymastercoins.com/jaddress.aspx?currency_id=2']} - - for coin in urls_list_dict.keys(): - urls=urls_list_dict[coin] - - dicts={} - for u in urls: - dicts[url_to_domain(u)]={} - - keys=dicts.keys() - - for u in urls: - filename='general/'+url_to_domain(u)+'-addresses.json' - debug('download json from '+u+' start') - response = urllib2.urlopen(u) - f = open(filename, "w") - f.write(response.read()) - f.close() - debug('download json from '+u+' done') - l=load_dict_from_file(filename, all_list=True) - for d in l: - dicts[url_to_domain(u)][d['address']]=d['balance'] - - for source in keys: - for addr in dicts[source].keys(): - compare_to=keys[:] - compare_to.remove(source) - for other in compare_to: - try: - if float(dicts[source][addr])!=float(dicts[other][addr]): - difference_dict[addr]='different' - except KeyError: - if float(dicts[source][addr]) != 0: # 0 is considered as nothing - difference_dict[addr]='not on '+other - - # collect detailed difference in text format - detailed_difference=coin+' consensus check at '+get_now()+'\n' - sources=keys[:] - for addr in difference_dict.keys(): - results=addr+': ' - last_value=-1 - add_line=False - for source in sources: - try: - value=str(float(dicts[source][addr])) - except KeyError: - value='0.0' - if last_value == -1: - last_value = float(value) - if float(value) != last_value: - add_line=True - results+=source+' '+value+'; ' - if add_line: - detailed_difference+=results+'\n' - - atomic_json_dump(difference_dict,'www/general/'+coin+'-difference.json') - f = open('www/general/'+coin+'-difference.txt', "w") - f.write(detailed_difference) - f.close() - - info('comparison done') - -if __name__ == "__main__": - compare() diff --git a/msc_compare_cron.sh b/msc_compare_cron.sh deleted file mode 100644 index fc3ddd8..0000000 --- a/msc_compare_cron.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -LOCK_FILE=/tmp/msc_compare_cron.lock -COMPARE_LOG=compare.log - -export PATH=$PATH:/usr/local/bin/ -cd /home/dev/mastercoin-tools/ - -# check lock (not to run multiple times) -[ -f $LOCK_FILE ] && exit 0 - -# lock -touch $LOCK_FILE - -python msc_compare.py 2>&1 > $COMPARE_LOG - -# unlock -rm -f $LOCK_FILE diff --git a/msc_cron.sh b/msc_cron.sh index f46d98e..8a8d81c 100644 --- a/msc_cron.sh +++ b/msc_cron.sh @@ -8,10 +8,6 @@ ARCHIVE_LOG=archived.log export PATH=$PATH:/usr/local/bin/ cd /home/dev/mastercoin-tools/ -# update external prices for wallet view -python msc_prices.py -cp www/currencies.json ../dev-mastercoin-tools/www/ - # check lock (not to run multiple times) [ -f $LOCK_FILE ] && exit 0 @@ -27,29 +23,12 @@ do x=$? done -python msc_validate.py 2>&1 > $VALIDATE_LOG - -# copy all results to web browser directory -cp tx/* www/tx/ -cp addr/* www/addr/ -cp general/* www/general/ -cp bids/* www/bids/ mkdir -p www/mastercoin_verify/addresses/ -cp mastercoin_verify/addresses/* www/mastercoin_verify/addresses/ mkdir -p www/mastercoin_verify/transactions/ -cp mastercoin_verify/transactions/* www/mastercoin_verify/transactions/ - -# copy also to dev site -cp tx/* ../dev-mastercoin-tools/www/tx/ -cp addr/* ../dev-mastercoin-tools/www/addr/ -cp general/* ../dev-mastercoin-tools/www/general/ -cp bids/* ../dev-mastercoin-tools/www/bids/ -mkdir -p ../dev-mastercoin-tools/www/mastercoin_verify/addresses/ -cp mastercoin_verify/addresses/* ../dev-mastercoin-tools/www/mastercoin_verify/addresses/ -mkdir -p ../dev-mastercoin-tools/www/mastercoin_verify/transactions/ -cp mastercoin_verify/transactions/* ../dev-mastercoin-tools/www/mastercoin_verify/transactions/ +python msc_validate.py 2>&1 > $VALIDATE_LOG # update archive +mkdir -p www/downloads/ python msc_archive.py 2>&1 > $ARCHIVE_LOG # unlock diff --git a/msc_prices.py b/msc_prices.py deleted file mode 100644 index e2326da..0000000 --- a/msc_prices.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/python - -####################################################### -# # -# Copyright Masterchain Grazcoin Grimentz 2013-2014 # -# https://github.com/grazcoin/mastercoin-tools # -# https://masterchain.info # -# masterchain@@bitmessage.ch # -# License AGPLv3 # -# # -####################################################### - -import os -import urllib2 -from optparse import OptionParser -from msc_utils_validating import * - -################################## -# main function - updates prices # -################################## -def update_prices(): - - # parse command line arguments - parser = OptionParser("usage: %prog [options]") - parser.add_option("-d", "--debug", action="store_true",dest='debug_mode', default=False, - help="turn debug mode on") - - (options, args) = parser.parse_args() - msc_globals.init() - msc_globals.d=options.debug_mode - - info('starting update prices') - - filename='general/bitcoinaverage_ticker_usd.json' - response = urllib2.urlopen('https://api.bitcoinaverage.com/ticker/USD/') - f = open(filename, "w") - f.write(response.read()) - f.close() - l=load_dict_from_file(filename, all_list=True) - bitcoin_avg=l['24h_avg'] - - filename='general/masterxchange_trades.json' - response = urllib2.urlopen('https://masterxchange.com/api/trades.php') - f = open(filename, "w") - f.write(response.read()) - f.close() - l=load_dict_from_file(filename, all_list=True) - total_paid=0 - total_amount=0 - for trade in l: - price=float(trade['price']) - amount=float(trade['amount']) - total_paid+=price*amount - total_amount+=amount - - mastercoin_avg=total_paid/total_amount - - msc_dict={"ID":"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P-0","name":"Mastercoin","symbol":"MSC", "dollar":mastercoin_avg*bitcoin_avg} - tmsc_dict={"ID":"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P-1","name":"Test Mastercoin","symbol":"TMSC","dollar":"0.0"} - bitcoin_dict={"ID":"Bitcoin","name":"Bitcoin","symbol":"BTC","dollar":bitcoin_avg} - - currencies_list=[msc_dict,tmsc_dict,bitcoin_dict] - atomic_json_dump(currencies_list,'www/currencies.json', add_brackets=False) - - info('update prices done') - -if __name__ == "__main__": - update_prices() diff --git a/www/404.html b/www/404.html deleted file mode 100644 index 3cbec6b..0000000 --- a/www/404.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - 404 - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-

404 - Page not found

-

Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry Sorry

-
-
-
- -
-
- - -
- - - - - diff --git a/www/API.html b/www/API.html deleted file mode 100644 index 1978dc2..0000000 --- a/www/API.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - API - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-

API

-

http://masterchain.info/tx/$TX_ID.json (e.g. here)

-

http://masterchain.info/addr/$ADDRESS.json (e.g. here)

-

http://masterchain.info/general/$CURRENCY_$PAGE.json (e.g. here)

-
-
- -
-
- -
-
- - - - - diff --git a/www/About.html b/www/About.html deleted file mode 100644 index 957d3b3..0000000 --- a/www/About.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - About - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-

About

-

This is the web UI of mastercoin-tools (License).

-

This project was done as part of Mastercoin coding contest.

-

Sync to bitcoin network is done using sx which connects to a local obelisk bitcoin node.

-

Links to additional tools.

-

-

Developers: Grazcoin and Grimentz.

-
-
-
- -
-
- - -
- - - - - diff --git a/www/Address.html b/www/Address.html deleted file mode 100644 index f57728e..0000000 --- a/www/Address.html +++ /dev/null @@ -1,440 +0,0 @@ - - - - - - - - - - Address information - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
-
- - - - - - - - - -
Address{{theAddress}}
Tools - - -
-
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Balance Information
Final balance{{addressInformation.balance}} -
Reserved{{addressInformation.total_reserved}} -
Bought via Exodus{{addressInformation.total_exodus}}
Payments received{{addressInformation.total_received}}
Payments sent{{addressInformation.total_sent}}
Coins bought{{addressInformation.total_bought}}
Coins sold{{addressInformation.total_sold}}
Open accept{{addressInformation.total_sell_accept}}
Open sell{{addressInformation.total_sell_offer}}
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Other Information
Currency{{currency}}
Exodus transactions{{addressInformation.exodus_transactions.length}}
Incoming transactions{{addressInformation.received_transactions.length}}
Outgoing transactions{{addressInformation.sent_transactions.length}}
Bought transactions{{addressInformation.bought_transactions.length}}
Sold transactions{{addressInformation.sold_transactions.length}}
Open accept transaction{{addressInformation.accept_transactions.length}}
Open sell transaction{{addressInformation.offer_transactions.length}}
-
-
-
-
- - - - - - - - - - - - - - - - -
Exodus transactions ({{addressInformation.exodus_transactions.length}})
TransactionAmountDate
- - {{trans.tx_hash | characters:10}} - {{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - - - - - - - - - - - - - - - -
Sold coins ({{addressInformation.sold_transactions.length}})
TransactionAmountDate
- - {{trans.tx_hash | characters:10}} - {{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - - - - - - - - - - - - - - -
Bought coins ({{addressInformation.bought_transactions.length}})
PaymentAcceptDate
- - {{trans.tx_hash | characters:10}} - - - - {{trans.accept_txid | characters:10}} - {{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - - - - - - - - - - - - - - - -
Sell offers ({{addressInformation.offer_transactions.length}})
TransactionAmountDate
- - {{trans.tx_hash | characters:10}} - {{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - - - - - - - - - - - - - - - -
Sell accepts ({{addressInformation.accept_transactions.length}})
TransactionAmountDate
- - {{trans.tx_hash | characters:10}} - {{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - - - - - - - - - - - - - - - - - -
Received transactions ({{addressInformation.received_transactions.length}})
TransactionSource addressAmountBlock time
- - {{trans.tx_hash | characters:10}} - {{trans.from_address}}{{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
- -
- - - - - - - - - - - - - - - - - - -
Sent transactions ({{addressInformation.sent_transactions.length}})
TransactionReceiving addressAmountBlock time
- - {{trans.tx_hash | characters:10}} - {{trans.to_address}}{{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
-
-
-
- - -
-
- -
-
-
- - - - diff --git a/www/License.html b/www/License.html deleted file mode 100644 index 136f2bd..0000000 --- a/www/License.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - License - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-

License

-

The code is distributed under AGPL v3 license.

-

This site uses glyphicons fonts.

-
-
-
- -
-
- - -
- - - - - diff --git a/www/Search.html b/www/Search.html deleted file mode 100644 index fe019a9..0000000 --- a/www/Search.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/www/acceptform.html b/www/acceptform.html deleted file mode 100644 index 1436455..0000000 --- a/www/acceptform.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - - - - Accept Sell Offer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
-

Accept sell offer -

-
- - - - -
- -

- -
-
-
- - -

- Exceeds sell offer -

-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -

-

-
-
- - - -
-
- -
-
- -
-
-
- - - - diff --git a/www/acceptform.js b/www/acceptform.js deleted file mode 100644 index 61c3f42..0000000 --- a/www/acceptform.js +++ /dev/null @@ -1,652 +0,0 @@ -var initialAmount = 0; -function AcceptOfferController($scope, $http) { - $scope.transactionInformation; - - $scope.footer = "FOOTER"; - $scope.title = "TITLE"; - - $scope.step = 0.1; - $scope.amount; - $scope.fee = 0.0005; - $scope.key = ""; - - $scope.keyChange = function () { - - if ($scope.key != "") { - $('#reSign').attr('disabled', false); - } - else { - $('#reSign').attr('disabled', true); - } - }; - - $scope.getSellofferData = function () { - - // parse tx from url parameters - var myURLParams = BTCUtils.getQueryStringArgs(); - var file = 'tx/' + myURLParams['tx'] + '.json'; - - // Make the http request and process the result - - $http.get(file, {}).success(function (data, status, headers, config) { - $scope.transactionInformation = data[0]; - - $scope.transactionInformation.formatted_amount = parseFloat($scope.transactionInformation.formatted_amount); - initialAmount = $scope.transactionInformation.formatted_amount; - - $scope.transactionInformation.to_address = 11; - //Create step for input type number - var amount = $scope.transactionInformation.formatted_amount.toString(); - //Whole number - if (amount.indexOf(".") == -1) { - console.log('Whole number'); - $scope.step = "1"; - } - else {//Decimal number - var decimalN = amount.substr(amount.indexOf(".") + 1); - var step = "0."; - for (var i = 0; i < decimalN.length - 1; i++) { - step += "0"; - } - step += "1"; - $scope.step = step; - } - }); - - } - - $scope.comboBoxValueChange = function () { - console.log($scope.transactionInformation); - } - - $scope.AmountChanged = function () { - $('#amountWarning').hide(); - if (initialAmount < $scope.transactionInformation.formatted_amount) { - // Amount higher than offer - Should tell the user that - console.log("blue warning"); - $('#amountWarning').show(); - } - } - - $('.invalidKey').hide(); -} - - - - - - - -//class for Context -BTNClientContext = new function () { -}; -//class for Signing -BTNClientContext.Signing = new function () { -}; - -BTNClientContext.Signing.Transaction = ""; - -BTNClientContext.Signing.ConvertRaw = function () { - - var str = BTNClientContext.Signing.Transaction; - str = str.replace(/[^0-9a-fA-f]/g, ''); - var bytes = Crypto.util.hexToBytes(str); - var sendTx = BTNClientContext.Signing.deserialize(bytes); - var text = BTNClientContext.toBBE(sendTx); - - return text; -} - -BTNClientContext.Signing.ConvertJSON = function (signedTransaction) { - - try { - $('.invalidTransaction').hide(); - var sendTx = BTNClientContext.fromBBE(signedTransaction); - - } - catch (e) { - $('.invalidTransaction').show(); - } - - - var rawTx = Crypto.util.bytesToHex(sendTx.serialize()); - - return rawTx; -}; - - -BTNClientContext.Signing.Verify = function () { - console.log("verify function"); - var buyer = $("input.select.optional.form-control.form-control30px.combobox").val(); - -var dataToSend = { addr: buyer }; - -var ok = true; -$.post('/wallet/validateaddr/', dataToSend, function (data) { -console.log('success'); -console.log(data); - -if (data.status == 'OK') { - ok = true; - $('#verifyMessage').addClass('greenText'); - $('#verifyMessage').text('OK'); - $('#verifyMessage').show(); - BTNClientContext.Resize(); - return ok; -} -else { - $('#verifyMessage').addClass('greenText'); - ok = false; - if (data.error == 'invalid pubkey') { - $('#verifyMessage').text('invalid pubkey'); - } else { - if (data.error == 'missing pubkey') { - $('#verifyMessage').text('no pubkey on blockchain. use wallet or supply Public Key from brainwallet.org'); - } else { - $('#verifyMessage').addClass('redText'); - if (data.error == 'invalid address') { - $('#verifyMessage').text('invalid address'); - } else { - $('#verifyMessage').text('invalid'); - } - } - } -} -$('#verifyMessage').show(); -BTNClientContext.Resize(); -return ok; -}).fail(function () { - -console.log('fail'); -$('#verifyMessage').text('ping?'); -$('#verifyMessage').addClass('redText'); - -ok = false; - -$('#verifyMessage').show(); -BTNClientContext.Resize(); -return ok; -}); - - - -}; - -BTNClientContext.Signing.SingSource = function () { -var hashType = 1; - -//Source Script for signing -var sourceScript = []; -var sourceScriptString = $('#sourceScript').val().split(';'); -$.each(sourceScriptString, function (i, val) { -sourceScript[i] = new BTNClientContext.parseScript(val); -console.log(val); -console.log($.toJSON(sourceScript[i])); -console.log(BTNClientContext.dumpScript(sourceScript[i])); -}); - -//create transaction object from BBE JSON -// var transactionBBE = $('#transactionBBE').val(); -var transactionBBE = BTNClientContext.Signing.ConvertRaw(BTNClientContext.Signing.Transaction); - -try { -$('.invalidTransaction').hide(); - var sendTx = BTNClientContext.fromBBE(transactionBBE); -} -catch (e) { - $('.invalidTransaction').show(); - return; -} - -//signature section -var eckey = BTNClientContext.GetEckey($('#privateKey').val()); //ECDSA -console.log($('#privateKey').val()); -console.log(Crypto.util.bytesToHex(eckey.getPubKeyHash())); -for (var i = 0; i < sendTx.ins.length; i++) { //for each input in the transaction -- sign it with the Key - -//console.log($.toJSON(sendTx)); -//console.log($.toJSON(sourceScript[i])); - -var hash = sendTx.hashTransactionForSignature(sourceScript[i], i, hashType); //Get hash of the transaction applying the soure script -console.log(Crypto.util.bytesToHex(hash)); - -var signature = eckey.sign(hash); //<---SIGN HERE -signature.push(parseInt(hashType, 10)); //add white space -var pubKey = eckey.getPub(); //public key - -//creating new in sript signature -var script = new Bitcoin.Script(); -script.writeBytes(signature); -script.writeBytes(pubKey); -//write sript signature -sendTx.ins[i].script = script; -} - -return BTNClientContext.toBBE(sendTx); -}; -//Should re sign transaction -- need to call all BC functions -BTNClientContext.Signing.ReSignTransaction = function () { -var reSigned = BTNClientContext.Signing.SingSource(); -BTNClientContext.Signing.TransactionBBE = reSigned; - -//show re-signed transaction -$('#signedTransactionBBE').val(reSigned); -BTNClientContext.Signing.RawChecked = false; -BTNClientContext.ToRawSigned(); -$('#RawRadioBtnSigned').addClass('active'); -$('#JsonRadioBtnSigned').removeClass('active'); - -//show hidden -$('#reSignClickedForm').show(); -}; - -BTNClientContext.Signing.SendTransaction = function () { - -var signedTransaction = $('#signedTransactionBBE').val(); - -//Maybe I need to convert to object from json string??? -var sendTx = BTNClientContext.fromBBE(signedTransaction); -var rawTx = Crypto.util.bytesToHex(sendTx.serialize()); -var dataToSend = { signedTransaction: rawTx }; -console.log(dataToSend); - -// Ajax call to /wallet/pushtx/ -$.post('/wallet/pushtx/', dataToSend, function (data) { -console.log('success'); -console.log(data); - - -}).fail(function () { - -// TODO This should be changed - Currently always fail as there is no server - -}); -}; - -BTNClientContext.Signing.GetRawTransaction = function () { - - -$('#statusMessage').removeClass('redText'); -$('#statusMessage').addClass('greenTextColor'); -$('#statusMessage').text(''); - - -$('#createRawResponseForm').hide(); - -var myURLParams = BTCUtils.getQueryStringArgs(); -var tx_hash = myURLParams['tx']; -var amount = $('#amount').val(); -var buyer = $('#buyerAddressOrPublicKey').val(); -if (!buyer) { - buyer = $("input.select.optional.form-control.form-control30px.combobox").val(); -} - -var dataToSend = { buyer: buyer, amount: amount, tx_hash: tx_hash }; -console.log(dataToSend); - -// Ajax call to /wallet/accept/ -$.post('/wallet/accept/', dataToSend, function (data) { -console.log('success'); -console.log(data); - -BTNClientContext.Signing.GetRawTransactionResponse(data); - -}).fail(function () { - -console.log('fail'); -var testResponse = { - 'status': 'ping?', - 'sourceScript': 'ERROR', - 'transaction': '' -}; -BTNClientContext.Signing.GetRawTransactionResponse(testResponse); - -}); -}; - -BTNClientContext.Signing.GetRawTransactionResponse = function (data) { - -var status = data.status; -if (!status) - status = data.error; -if (status && status != "OK" && status != "Ok" && status != "ok") { -if (status.length > 120) { - //take first 117 and add ... - status = status.substr(0, 117); - status += "..."; -} - -$('#statusMessage').removeClass('greenTextColor'); -$('#statusMessage').addClass('redText'); -$('#statusMessage').text(status); - - -$('#createRawResponseForm').hide(); -return; -} - -BTNClientContext.Signing.Transaction = data.transaction; - -//Init fields values -//data should have fields sourceScript and transaction -$('#sourceScript').val(data.sourceScript); -$('#transactionBBE').val(data.transaction); - -//Showing the fields -$('#createRawResponseForm').show(); - -}; - - - -// HISTORY of Buyer address or public key - -BTNClientContext.Signing.supportsStorage = function () { -try { -return 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - return false; - } -}; - -BTNClientContext.Signing.initHistoryCombobox = function () { - var myURLParams = BTCUtils.getQueryStringArgs(); - var useAddress = myURLParams['from']; - - var showValuesInCombobox = Wallet.GetAddressesOfFirstWallet(); - - if (useAddress) { - if (showValuesInCombobox.indexOf(useAddress) == -1) { - showValuesInCombobox.splice(0, 0, useAddress); - } - } - - $.each(showValuesInCombobox, function (key, value) { - - console.log(key); - console.log(value); - - $('#buyerAddressOrPublicKey') - .append($("") - .attr("value", value) - .text(value)); - - //.attr("value", value.address) - // .text(value.address)); - }); - - if (useAddress) { - $("#buyerAddressOrPublicKey").val(useAddress); - } - - $("#buyerAddressOrPublicKey").combobox(); -}; - -BTNClientContext.Signing.addAddressToHistory = function () { - if (BTNClientContext.Signing.supportsStorage()) { - - var address = $("input.select.optional.form-control.form-control30px.combobox").val(); - var history; - if (localStorage["Addresses"]) { - history = JSON.parse(localStorage["Addresses"]); - if (history.length > 9) { - history.shift(); - } - var addr = { 'address': address }; - - // Check if the addr is in the array already and if it is delete it - // var index = history.indexOf(addr); - var index = history.indexOf(address); - if (index > -1) { - history.splice(index, 1); - } - - //add new address to array - // history.push(addr); - history.push(address); - - localStorage["Addresses"] = JSON.stringify(history); - } - else { // If the localStorage["Addresses"] doesn't exists - // var addr = { 'address': address }; - var que = []; - // que.push(addr); - que.push(address); - localStorage["Addresses"] = JSON.stringify(que); - } - - // console.log(localStorage["Addresses"]); - } -}; -$(document).ready(function myfunction() { - - $('#sendLoader').addClass('hideLoader'); - - //Combbox init - BTNClientContext.Signing.initHistoryCombobox(); - - - - BTNClientContext.Resize(); - - - var navHeight = $('.navbar').height(); - $('.page-container').css('paddingTop', navHeight + 20); - - - //disable btn at the beggining, because it needs to have a value in a privateKey - $('#reSign').attr('disabled', true); - - - $('#createRawTransaction').click(function () { - $('#createRawTransactionLoader').show(); - - BTNClientContext.Signing.GetRawTransaction(); - - - //Add address to history - BTNClientContext.Signing.addAddressToHistory(); - - $('#createRawTransactionLoader').hide(); - }); - - $('#reSign').click(function () { - - $('.invalidKey').hide(); - $('.invalidTransaction').hide(); - - $('#reSignLoader').show(); - try { - BTNClientContext.Signing.ReSignTransaction(); - } - catch (e) { - console.log(e); - $('.invalidKey').show(); - $('.invalidTransaction').show(); - - - //If the key is invalid the resigned transaction form is hidden again - $('#reSignClickedForm').hide(); - - } - $('#reSignLoader').hide(); - }); - - $('#send').click(function () { - $('#sendLoader').addClass('showUntilAjax'); - $('#sendLoader').addClass('show3sec'); - var sendLoaderInterval = setInterval(function () { - $('#sendLoader').removeClass('show3sec'); - clearInterval(sendLoaderInterval); - }, 3000); - //BTNClientContext.Signing.SendTransaction(); - BTNClientContext.txSend(); - - - }); - - $('#verifyButton').click(function () { - $('#verifyMessage').hide(); - $('#verifyLoader').show(); - - //If returned ok then add address to history - if (BTNClientContext.Signing.Verify()) { - BTNClientContext.Signing.addAddressToHistory(); - - console.log('added to history'); - } - else { - console.log('not verified and not ok'); - } - - $('#verifyLoader').hide(); - }); - - //$("#rawJsonRadio").click(function () { - - // console.log(BTNClientContext.Signing.Transaction); - // var converted = ""; - // if ($('#RawRadioBtn').hasClass('active')) { //It raw has class active it means that the json state is selected now - // converted = BTNClientContext.Signing.ConvertRaw(); - // } - // else { //the raw state is selected now - // converted = BTNClientContext.Signing.Transaction; - // } - - // $('#transactionBBE').val(converted); - //}); - $('#JsonRadioBtn').click(function () { - var converted = BTNClientContext.Signing.ConvertRaw(BTNClientContext.Signing.Transaction); - $('#transactionBBE').val(converted); - }); - $('#RawRadioBtn').click(function () { - var converted = BTNClientContext.Signing.Transaction; - $('#transactionBBE').val(converted); - }); - - - $('#JsonRadioBtnSigned').click(function () { - if (BTNClientContext.Signing.RawChecked == true) { - var rawTransaction = $('#signedTransactionBBE').val(); - var converted = BTNClientContext.Signing.ConvertRaw(rawTransaction); - $('#signedTransactionBBE').val(converted); - $('#signedTransactionBBE').attr('readonly', false); - BTNClientContext.Signing.RawChecked = false; - } - }); - - BTNClientContext.Signing.RawChecked = true; - $('#RawRadioBtnSigned').click(function () { - BTNClientContext.ToRawSigned(); - if ($('.invalidTransaction').is(":visible")) { - console.log('Json is invalid'); - $('#RawRadioBtnSigned').removeClass('active'); - $('#JsonRadioBtnSigned').addClass('active'); - - } - }); - -}); - -BTNClientContext.ToRawSigned = function() { - if (BTNClientContext.Signing.RawChecked == false) { - var converted = ""; - try { - var signedTransaction = $('#signedTransactionBBE').val(); - converted = BTNClientContext.Signing.ConvertJSON(signedTransaction); - $('#signedTransactionBBE').attr('readonly', false); - BTNClientContext.Signing.RawChecked = true; - } - catch (e) { - converted = $('#signedTransactionBBE').val(); - - $('#RawRadioBtnSigned').removeClass('active'); - $('#JsonRadioBtnSigned').addClass('active'); - - - } - $('#signedTransactionBBE').val(converted); - } -} - -BTNClientContext.Resize = function () { - // console.log($('#amount').width()); - var width = $('#amount').width() - 25; - - var left = $('#verifyButton').offset().left + 70; - // console.log(left); - $('#verifyMessage').width(width); - $('#verifyMessage').offset({ left: left }); -}; - -$(window).resize(function () { - BTNClientContext.Resize(); -}); - -function txSent(text) { -alert(text ? text : 'No response!'); -} - -BTNClientContext.txSend = function() { - $('#sendHyperlink').hide(); - $('#sendMessage').hide(); - BTNClientContext.ToRawSigned(); - $('#RawRadioBtnSigned').addClass('active'); - $('#JsonRadioBtnSigned').removeClass('active'); - - var rawTx = $('#signedTransactionBBE').val(); - //var sendTx = BTNClientContext.fromBBE(signedTransaction); - //var rawTx = Crypto.util.bytesToHex(sendTx.serialize()); - - //url = 'http://bitsend.rowit.co.uk/?transaction=' + tx; - url = 'http://blockchain.info/pushtx'; - postdata = 'tx=' + rawTx; - - if (url != null && url != "") { - BTNClientContext.tx_fetch(url, txSent, txSent, postdata); - } - return false; -} - -// Some cross-domain magic (to bypass Access-Control-Allow-Origin) -BTNClientContext.tx_fetch = function(url, onSuccess, onError, postdata) { - var useYQL = true; - - if (useYQL) { - var q = 'select * from html where url="'+url+'"'; - if (postdata) { - q = 'use "https://dev.masterchain.info/js/htmlpost.xml" as htmlpost; '; - q += 'select * from htmlpost where url="' + url + '" '; - q += 'and postdata="' + postdata + '" and xpath="//p"'; - } - url = 'https://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(q); - } - - $.ajax({ - url: url, - success: function(res) { - $('#sendLoader').removeClass('showUntilAjax'); - - $('#sendMessage').text('Transaction sent'); - $('#sendMessage').addClass('greenTextColor'); - $('#sendMessage').show(); - - //Get transaction hash code - var link = "https://blockchain.info/tx/"; - //signed transaction code - var code = JSON.parse(BTNClientContext.Signing.TransactionBBE).hash; - - link += code; - $('#sendLink').attr('href', link); - $('#sendLink').text(link); - $('#sendHyperlink').show(); - }, - error:function (xhr, opt, err) { - $('#sendMessage').text('Transaction send error'); - $('#sendMessage').addClass('redText'); - $('#sendMessage').show(); - $('#sendLoader').removeClass('showUntilAjax'); - } - }); -} - diff --git a/www/addr/.gitignore b/www/addr/.gitignore deleted file mode 100644 index 88ced2e..0000000 --- a/www/addr/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# json -*.json diff --git a/www/address.js b/www/address.js deleted file mode 100644 index feae2bb..0000000 --- a/www/address.js +++ /dev/null @@ -1,121 +0,0 @@ -function AdressController($scope, $http) { - $scope.addressInformation = {}; - $scope.theAddress = ""; - $scope.footer = "FOOTER"; - $scope.title = "TITLE"; - - $scope.createIconPopup = function () { - $('.iconPopupInit').popover({ trigger: "hover" }); - }; - - $scope.paymentsReceivedSum = function (currencyId) { - var length = $scope.addressInformation.received_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.received_transactions[i].currency_id == currencyId) { - sum += parseFloat($scope.addressInformation.received_transactions[i].amount); - } - } - return sum; - } - - $scope.boughtViaExodusSum = function (currencyId) { - - var length = $scope.addressInformation.exodus_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.exodus_transactions[i].currency_id == currencyId) { - sum += parseFloat($scope.addressInformation.exodus_transactions[i].amount); - } - - } - return sum; - } - //paymentsSentSum - $scope.paymentsSentSum = function (currencyId) { - var length = $scope.addressInformation.sent_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.sent_transactions[i].currency_id == currencyId) { - sum += parseFloat($scope.addressInformation.sent_transactions[i].amount); - } - } - return sum; - } - - //Count of the transactions - $scope.incomingTransCount = function (currencyId) { - var length = $scope.addressInformation.received_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.received_transactions[i].currency_id == currencyId) { - sum++; - } - - } - return sum; - } - - $scope.outgoingTransCount = function (currencyId) { - var length = $scope.addressInformation.sent_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.sent_transactions[i].currency_id == currencyId) { - sum++; - } - - } - return sum; - } - - $scope.exodusTransCount = function (currencyId) { - var length = $scope.addressInformation.exodus_transactions.length; - var sum = 0; - for (var i = 0; i < length; i++) { - if ($scope.addressInformation.exodus_transactions[i].currency_id == currencyId) { - sum++; - } - - } - return sum; - } - - $scope.getAddressData = function () { - - // parse addr from url parameters - var myURLParams = BTCUtils.getQueryStringArgs(); - $scope.theAddress = myURLParams['addr']; - $('#qrcode').qrcode({ - width: 130, - height: 130, - text: myURLParams['addr'] - }); - var file = 'addr/' + myURLParams['addr'] + '.json'; - var currencyName = myURLParams['currency']; - if (currencyName == 'MSC') { - currencyNumber = 0; - } - if (currencyName == 'TMSC') { - currencyNumber = 1; - } - // Make the http request and process the result - $http.get(file, {}).success(function (data, status, headers, config) { - $scope.addressInformation = data[currencyNumber]; - }); - } - - $scope.SendClick = function () { - var myURLParams = BTCUtils.getQueryStringArgs(); - var url = "sendform.html?addr="; - url += myURLParams['addr']; - url += "¤cy="; - url += myURLParams['currency']; - window.location = url; - } - - $scope.AddToWalletClick = function () { - var myURLParams = BTCUtils.getQueryStringArgs(); - var addr = myURLParams['addr']; - Wallet.AddAddress(addr); - } -} diff --git a/www/btc02.js b/www/btc02.js deleted file mode 100644 index aabe74c..0000000 --- a/www/btc02.js +++ /dev/null @@ -1,290 +0,0 @@ -function BTCController($scope, $http) { - - // Scope members - $scope.transactions = {}; - $scope.caption = ''; - $scope.pages = {}; - $scope.showPages = 5; - $scope.currentPageStart = 1; - $scope.currentPage = 1; - $scope.numberOfPages = 12; // this we will get somehow from the server - $scope.firstLoad = true; - $scope.prevClass='disabled'; - $scope.nextClass=''; - - $scope.createIconPopup = function () { - $('.iconPopupInit').popover({ trigger: "hover" }); - }; - - $scope.$on('handlePagesBroadcast', function(event, args) { - $scope.numberOfPages = Number(args.message); - $scope.showPages = Math.min(5, $scope.numberOfPages); - $scope.pages = $scope.pagesCreator($scope.currentPageStart); - }); - - $scope.getData = function ($i) { - // parse currency from url parameters - var myURLParams = BTCUtils.getQueryStringArgs(); - - // Set title - if (myURLParams['filter'] && myURLParams['filter'].length > 0) { - document.title = "Recent " + myURLParams['filter']; - } - // Clear scope members - $scope.currentPageStart = (1+$i-($i%$scope.showPages)); - if ($scope.currentPageStart>$i) - $scope.currentPageStart-=$scope.showPages; - if ($scope.currentPageStart+$scope.showPages>$scope.numberOfPages) - $scope.currentPageStart=$scope.numberOfPages-$scope.showPages+1; - $scope.currentPage=$i; - $scope.transactions = {}; - $scope.caption = 'Latest Mastercoin transactions'; - - var num=str_pad($i, 4, '0', 'STR_PAD_LEFT'); - var filter = (myURLParams['filter'] && myURLParams['filter'].length > 0)? myURLParams['filter'] + "_" : ""; - var file = 'general/' + myURLParams['currency'] + '_' + filter + num + '.json'; - // Make the http request and process the result - $http.get( - file, - { - - }).success(function (data, status, headers, config) { - angular.forEach(data, function(item) { - item.source = num; - }); - $scope.transactions = data; - }); - $scope.initPages($scope.currentPageStart); - } -$scope.initPages = function($n) { - $scope.pages = $scope.pagesCreator($n); - } - - - $scope.prevPages = function() { - if ($scope.prevClass=='') { - $scope.currentPageStart=$scope.currentPageStart-$scope.showPages; - if ($scope.currentPageStart<1) { - $scope.currentPageStart=1; - } - $scope.pages = $scope.pagesCreator($scope.currentPageStart); - } - } - - $scope.nextPages = function() { - if ($scope.nextClass=='') { - $scope.currentPageStart=$scope.showPages+$scope.currentPageStart; - if ($scope.currentPageStart>$scope.numberOfPages-$scope.showPages+1) { - $scope.currentPageStart=$scope.numberOfPages-$scope.showPages+1; - } - $scope.pages = $scope.pagesCreator($scope.currentPageStart); - } - } - - $scope.partToggle = function($i) { - var num=str_pad($i, 4, '0', 'STR_PAD_LEFT'); - var startIndex = $scope.findFirstIndex(num); - if (startIndex == -1){ - var myURLParams = BTCUtils.getQueryStringArgs(); - var filter = (myURLParams['filter'] && myURLParams['filter'].length > 0)? myURLParams['filter'] + "_" : ""; - var file = 'general/' + myURLParams['currency'] + '_' + filter + num + '.json'; - $http.get(file).success(function (data, status, headers, config) { - angular.forEach(data, function(item) { - item.source = num; - }); - $scope.transactions = $scope.transactions.concat(data); - $scope.pages[$i-$scope.currentPageStart]["img"] = "remove"; - $scope.pages[$i-$scope.currentPageStart]["class"] = "selected"; - }); - }else{ - $scope.transactions.splice(startIndex, 10); - $scope.pages[$i-$scope.currentPageStart]["img"] = "add"; - $scope.pages[$i-$scope.currentPageStart]["class"] = ""; - } - } - - $scope.pagesCreator = function(start){ - var to_show= new Array(); - for (var i = 0; i < $scope.showPages && i+start <=$scope.numberOfPages && i+start>0; i++) { - to_show[i] = {}; - to_show[i]["number"] = start+i; - if($scope.findFirstIndex(str_pad(i+start, 4, '0', 'STR_PAD_LEFT'))== -1 && start+i!=$scope.currentPage ){ - to_show[i]["img"] = "add"; - to_show[i]["class"] = ""; - }else{ - to_show[i]["img"] = "remove"; - to_show[i]["class"] = "selected"; - $scope.firstLoad=false; - } - } - if (start>1) { - $scope.prevClass=''; - }else{ - $scope.prevClass='disabled'; - } - - if ($scope.currentPageStart+$scope.showPages<=$scope.numberOfPages) { - $scope.nextClass=''; - }else{ - $scope.nextClass='disabled'; - } - return to_show; - } - - $scope.findFirstIndex = function(itemSource) { - for(var i = 0; i < $scope.transactions.length; i++) { - if ($scope.transactions[i].source == itemSource) { - return i; - } - } - return -1; // not found - } -} - -function str_pad (input, pad_length, pad_string, pad_type) { - var half = '', - pad_to_go; - - var str_pad_repeater = function (s, len) { - var collect = '', - i; - - while (collect.length < len) { - collect += s; - } - collect = collect.substr(0, len); - - return collect; - }; - - input += ''; - pad_string = pad_string !== undefined ? pad_string : ' '; - - if (pad_type !== 'STR_PAD_LEFT' && pad_type !== 'STR_PAD_RIGHT' && pad_type !== 'STR_PAD_BOTH') { - pad_type = 'STR_PAD_RIGHT'; - } - if ((pad_to_go = pad_length - input.length) > 0) { - if (pad_type === 'STR_PAD_LEFT') { - input = str_pad_repeater(pad_string, pad_to_go) + input; - } else if (pad_type === 'STR_PAD_RIGHT') { - input = input + str_pad_repeater(pad_string, pad_to_go); - } else if (pad_type === 'STR_PAD_BOTH') { - half = str_pad_repeater(pad_string, Math.ceil(pad_to_go / 2)); - input = half + input + half; - input = input.substr(0, pad_length); - } - } - - return input; -} - -$(document).ready(function () { - SearchHistoryContext.initHistoryCombobox(); - - - //Add padding to the body - var navHeight = $('.navbar').height(); - $('.page-container').css('paddingTop', navHeight + 20); - console.log('CHanged padding of body'); - - - $('#btnSearch').click(function () { - - SearchHistoryContext.addSearchToHistory(); - - - //redirect to Search.html?tx= - var searchTerm = $('.combobox-container .select').val(); - - window.location.href = "Search.html?tx=" + searchTerm; - - }); -}); - -SearchHistoryContext = new function () { -}; - -SearchHistoryContext.initHistoryCombobox = function () { - if (SearchHistoryContext.supportsStorage()) { - - console.log(localStorage["Search"]); - if (localStorage["Search"]) { - - var addresses = localStorage["Search"]; - var history = JSON.parse(addresses); - - console.log(history); - - //if there is something in history add to combobox - var showValuesInCombobox = history.reverse(); - $.each(showValuesInCombobox, function (key, value) { - - console.log(key); - console.log(value); - - $('#searchText') - .append($("") - .attr("value", value) - .text(value)); - - }); - - } - $("#searchText").combobox(); - - - //Add button in here - - $('.search .combobox-container').append($("") - .text('Search')); - - //Placeholder - $('.search .combobox-container .customDropdown').attr("placeholder", "Address or Transaction"); - - } - else { - //Doesn't support storage, do nothing - } -}; - -SearchHistoryContext.supportsStorage = function () { - try { - return 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - return false; - } -}; - -SearchHistoryContext.addSearchToHistory = function () { - if (SearchHistoryContext.supportsStorage()) { - - // var address = $("input.select.optional.form-control.form-control30px.combobox").val(); - var search = $('.combobox-container .select').val(); - - console.log(search); - - var history; - if (localStorage["Search"]) { - history = JSON.parse(localStorage["Search"]); - if (history.length > 9) { - history.shift(); - } - - var index = history.indexOf(search); - if (index > -1) { - history.splice(index, 1); - } - - history.push(search); - - localStorage["Search"] = JSON.stringify(history); - } - else { - var que = []; - que.push(search); - localStorage["Search"] = JSON.stringify(que); - } - - } -}; - diff --git a/www/btcpayment.html b/www/btcpayment.html deleted file mode 100644 index 351f961..0000000 --- a/www/btcpayment.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - Bitcoin Payment - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- - - - - -
Transaction{{transactionInformation.tx_hash}}
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bitcoin payment details
From{{transactionInformation.from_address}}
- To {{f.address | characters:10}} - - {{f.value}} ฿ -
CurrencyBitcoin
Fee{{transactionInformation.fee}} ฿
Sell Offer{{transactionInformation.sell_offer_txid}}
Accept Offer{{transactionInformation.accept_txid}}
-
-
- - - - - - - - - - - - - - - - - - - - -
Information
Transaction type - - Bitcoin payment
Included in block{{transactionInformation.block}}
Index in block{{transactionInformation.index}}
Block time{{transactionInformation.tx_time | date:'yyyy-MM-dd HH:mm:ss UTC'}}
-
-
-
-
- -
-
- -
-
-
- - - - diff --git a/www/btcpayment.js b/www/btcpayment.js deleted file mode 100644 index becf92f..0000000 --- a/www/btcpayment.js +++ /dev/null @@ -1,52 +0,0 @@ -function TransactionController($scope, $http) { - $scope.transactionInformation; - $scope.fees; - $scope.footer = "FOOTER"; - $scope.title = "TITLE"; - $scope.reason = "unknown"; - - $scope.createIconPopup = function () { - $('.iconPopupInit').popover({ trigger: "hover" }); - }; - - //Function for creating popup - $scope.makePopup = function () { - //Popup for valid/invalid - $('#validPopup').popover({ trigger: "hover" }); - var navHeight = $('.navbar').height(); - $('.page-container').css('paddingTop', navHeight + 20); - }; - - $scope.getTransactionData = function () { - - // parse tx from url parameters - var myURLParams = BTCUtils.getQueryStringArgs(); - var file = 'tx/' + myURLParams['tx'] + '.json'; - // Make the http request and process the result - $http.get(file, {}).success(function (data, status, headers, config) { - var toAddressArray = []; - var toAddr = data[0].to_address; - var arr1 = toAddr.split(";"); - var length = arr1.length; - for (var i = 0; i < length ; i++) { - var p = arr1[i].split(":"); - - toAddressArray[i] = { "address": p[0], "value": p[1] }; - } - - console.log(toAddressArray); - data[0].to_address = toAddressArray; - $scope.transactionInformation = data[0]; - $scope.setDefaults(); - }); - } - - $scope.setDefaults = function() { - if (!$scope.transactionInformation.icon_text) { - $scope.transactionInformation.icon_text = "Bitcoin payment"; - } - if (!$scope.transactionInformation.color) { - $scope.transactionInformation.color = "bgc-default"; - } - } -} diff --git a/www/btcutils.js b/www/btcutils.js deleted file mode 100644 index 5d5ab94..0000000 --- a/www/btcutils.js +++ /dev/null @@ -1,37 +0,0 @@ - -function BTCUtils() { -} - -///// Public Methods - - -BTCUtils.getQueryStringArgs = function () { - //get query string without the initial ? - var qs = (location.search.length > 0 ? location.search.substring(1) : ""), - //object to hold data - args = {}, - //get individual items - items = qs.length ? qs.split("&") : [], - item = null, - name = null, - value = null, - //used in for loop - i = 0, - len = items.length; - //fill defaults - args['title']='Masterchain data' - args['tx']='sample_tx' - args['addr']='sample_addr' - args['currency']='MSC' - args['page']='0000' - //assign each item onto the args object - for (i=0; i < len; i++){ - item = items[i].split("="); - name = decodeURIComponent(item[0]); - value = decodeURIComponent(item[1]); - if (name.length) { - args[name] = value; - } - } - return args; -} diff --git a/www/css/acceptform.css b/www/css/acceptform.css deleted file mode 100644 index e111536..0000000 --- a/www/css/acceptform.css +++ /dev/null @@ -1,179 +0,0 @@ -.amountWarning { - display: none; - position: absolute; - right: -120px; - margin-top: -25px; - color:#0094ff; -} - .verifyButton{ - - position: absolute; - right: -60px; - margin-top: -39px; - - } - - .verifySendStatus { - display: none; - position: absolute; - margin-top: -32px; - margin-left: 70px; - } - - .verifyMessage{ - display:none; - position: absolute; - margin-top: -32px; - } - - #sendHyperlink{ - display:none; - } - - .verifyLoader{ - display:none; - position: absolute; - right: -90px; - margin-top: -35px; - } - - .loader { - width: 24px; - height: 24px; - display: none; - } - - .showUntilAjax{ - display:inline; - } - .show3sec{ - display:inline !important; -} - - .redText{ - color:#d93838; - } - .greenText{ - color:#27dd3f; - right: -90px; - } - -.invalidKey { - display: none; - position: absolute; - right: -60px; - margin-top: -27px; - } - -.invalidTransaction { - /*display:none;*/ - position: absolute; - right: -105px; - margin-top: -130px; -} -@media only screen and (max-width: 991px) { - /*@media only screen and (max-width: 970px) {*/ - .amountWarning{ - position:relative; - right:0; - margin-top:5px; - } - .verifyButton{ - position:relative; - right:0; - margin-top:5px; - } - .verifyMessage{ - margin-top: -27px; - } - - .verifyLoader { - position: absolute; - /*right: -90px;*/ - left: 80px; - margin-top: -30px; - } - - .invalidKey { - position: relative; - right: 0px; - margin-top: 0px; - } - - .invalidTransaction { - position: relative; - right: 0px; - margin-top: 0px; - } -} - - .textareaScroll[readonly] { - cursor:default !important; - } - -#buyerAddressOrPublicKeyDiv .custom-combobox { - position: relative; - display: inline-block; - } -#buyerAddressOrPublicKeyDiv .custom-combobox-toggle { - position: absolute; - top: 0; - bottom: 0; - margin-left: -1px; - padding: 0; - /* support: IE7 */ - *height: 1.7em; - *top: 0.1em; - } -#buyerAddressOrPublicKeyDiv .custom-combobox-input { - margin: 0; - padding: 0.3em; - } - .form-control30px{ - width:calc(100% - 30px); - - } - -#buyerAddressOrPublicKeyDiv .combobox-container .add-on { - height: 34px !important; - width: 30px; -} - -.combobox-selected { -} - -#buyerAddressOrPublicKeyDiv .combobox-selected .caret { - display: inline-block; -} - - - - .textareaScroll{ - overflow-y:scroll; - resize:none; - - } - - -#rawJsonRadio { - margin-top: 4px; -} - -#rawJsonRadioSigned { - margin-top: 4px; -} - - - .input.string.optional{ - margin-bottom:12px; - } - - #createRawResponseForm, #reSignClickedForm{ - margin-top:12px; - } - - - .btnMargin{ - margin-top:4px; - margin-bottom:12px; - } \ No newline at end of file diff --git a/www/css/bootstrap-combobox.css b/www/css/bootstrap-combobox.css deleted file mode 100644 index 46e09b9..0000000 --- a/www/css/bootstrap-combobox.css +++ /dev/null @@ -1,150 +0,0 @@ -.combobox-container { - margin-bottom: 5px; - *zoom: 1; -} -.combobox-container:before, -.combobox-container:after { - display: table; - content: ""; -} -.combobox-container:after { - clear: both; -} -.combobox-container input, -.combobox-container .uneditable-input { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.combobox-container input:focus, -.combobox-container .uneditable-input:focus { - position: relative; - z-index: 2; -} -.combobox-container .uneditable-input { - border-left-color: #ccc; -} -.combobox-container .add-on { - float: left; - display: inline-block; - width: auto; - min-width: 16px; - height: inherit !important; - margin-right: -1px; - padding: 4px 5px; - font-weight: normal; - color: #999999; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #f5f5f5; - border: 1px solid #ccc; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; - -} -.combobox-container .active { - background-color: #a9dba9; - border-color: #46a546; -} -.combobox-container input, -.combobox-container .uneditable-input { - float: left; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.combobox-container .uneditable-input { - border-left-color: #eee; - border-right-color: #ccc; -} -.combobox-container .add-on { - margin-right: 0; - margin-left: -1px; - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.combobox-container input:first-child { - *margin-left: -160px; -} -.combobox-container input:first-child + .add-on { - *margin-left: -21px; -} -.combobox-container select { - display: inline-block; - width: 0; - height: 0; - border: 0; - padding: 0; - margin: 0; - text-indent: -99999px; - *text-indent: 0; -} -.form-search .combobox-container, -.form-inline .combobox-container { - display: inline-block; - margin-bottom: 0; - vertical-align: top; -} -.form-search .combobox-container .add-on, -.form-inline .combobox-container .add-on { - vertical-align: middle; -} -.combobox-selected .combobox-clear { - display: inline-block; -} -.combobox-selected .caret { - display: none; -} -.combobox-clear { - display: none; - width: 14px; - height: 14px; - line-height: 14px; - vertical-align: top; - opacity: 0.3; - filter: alpha(opacity=30); -} -.dropdown:hover .combobox-clear, -.open.dropdown .combobox-clear { - opacity: 1; - filter: alpha(opacity=100); -} -.btn .combobox-clear { - margin-top: 1px; - margin-left: 1px; -} -.btn:hover .combobox-clear, -.open.btn-group .combobox-clear { - opacity: 1; - filter: alpha(opacity=100); -} -.typeahead-long { - max-height: 300px; - overflow-y: auto; -} -.control-group.error .combobox-container .add-on { - color: #B94A48; - border-color: #B94A48; -} -.control-group.error .combobox-container .caret { - border-top-color: #B94A48; -} -.control-group.warning .combobox-container .add-on { - color: #C09853; - border-color: #C09853; -} -.control-group.warning .combobox-container .caret { - border-top-color: #C09853; -} -.control-group.success .combobox-container .add-on { - color: #468847; - border-color: #468847; -} -.control-group.success .combobox-container .caret { - border-top-color: #468847; -} -.btn .combobox-clear [class^="icon-"] { - line-height: 1.4em; -} \ No newline at end of file diff --git a/www/css/bootstrap-theme.css b/www/css/bootstrap-theme.css deleted file mode 100644 index 2fa10c1..0000000 --- a/www/css/bootstrap-theme.css +++ /dev/null @@ -1,405 +0,0 @@ - -.navbar .navbar-brand{ - padding:10px 15px; -} - -a.navbar-brand img:first-of-type { - height: 32px; -} - -.navbar a.navbar-title{ - padding-top: 22px; - padding-left:20px; - font-size:26px; - color:#105D91; - font-weight: 500; - background: -webkit-linear-gradient(#2781B4, #004478); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; -} - -.jumbotron.left_bar{ - padding:10px; - font-size: 1em; - height: 100%; - overflow: hidden; -} - -html, -body { - height: 100%; - /* The html and body elements cannot have any padding or margin. */ - -} - -@media (min-width: 768px) and (max-width: 991px) { - .c-visible-xs { - display:none !important; - } -} - -@media screen and (max-width: 991px) { - #qrcode { - float: none !important; - display: table; - margin: 0 auto; - } - .qrcode-address { - width: 100%; - } -} - -/* -@media (max-width: 1000px) -.navbar > .container .navbar-brand { -margin-right: -1000px; -} - -@media screen and (max-width: 991px) { - body { padding-top: 40px; } -} - -@media screen and (max-width: 768px) { - body { padding-top: 0px; } -} - -@media screen and (max-width: 510px) { - body { padding-top: 40px; } -} -*/ -/* Wrapper for page content to push down footer */ -#wrap { - min-height: 100%; - height: auto !important; - height: 100%; - /* Negative indent footer by it's height */ - margin: 0 auto -60px; -} - -/* Set the fixed height of the footer here */ -#push, -#footer { - height: 60px; -} -#footer { - background-color: #f5f5f5; -} -#footer .container{ - margin:auto; - -} -/* Lastly, apply responsive CSS fixes as necessary */ -@media (max-width: 767px) { - #footer { - margin-left: -20px; - padding-left: 20px; - padding-right: 20px; - } - .col-xs-6.no-padding{ - padding-right:5px; - } -} - - -/* Custom page CSS --------------------------------------------------- */ -/* Not required for template or sticky footer method. */ - -.c-footer-container { - position: relative; -} - -.container .credit { - margin: 20px 0; - width: 320px; - float:left; - z-index: 20; - position: absolute; -} - -.container .credit-static { - margin: 20px 0 !important; -} - -.revision { - margin-top: 5px; - margin-bottom: 0px; - font-size: 75%; - right: 10px; - width: 320px; - z-index: 10; - position: absolute; -} - -code { - font-size: 80%; -} - -.panel-heading.ng-binding{ - padding: 5px; - line-height: 25px; -} -table caption{ - font-size:1.2em; - padding: 4px; - font-weight: bold; - background: #eeeeee; - color:#444444; - -webkit-border-radius: 5px 5px 0px 0px; - border-radius: 5px 5px 0px 0px; -} -table th{ - color: #333333; -} -.panel-body{ - padding:0px 5px; -} -table.table{ - table-layout:fixed; -} -table.table td{ - white-space:nowrap; - overflow:hidden; - text-overflow:ellipsis; -} - -.btnCell { - white-space:normal !important; -} - -table.table td a{ padding: 0; margin: 0; line-height: 1em;} -table.table tr { height: 30px;} -td.test{ - width:50px; -} -.container{ - margin:0 auto; -} -.page-container{ - padding-top:70px; -} -.no-padding{ - padding:0; -} - -.falseValidState { - background-color: #5cb85c !important; - color: white; -} - - .falseValidState::after { - content: "Valid"; - } - - .falseValidStateDiv,.falseValidStateDiv:hover { - background-color: #5cb85c !important; - color: white; -} - - .trueValidStateDiv, .trueValidStateDiv:hover{ - background-color: #d9534f !important; - color: white; - } - -.trueValidState { - background-color: #d9534f !important; - color: white; -} - - .trueValidState::after { - content: "Invalid"; - } - -.popover-content { - color: black; - -ms-word-wrap: break-word; - word-wrap: break-word; -} - - -.popover-title{ - background-color: #d9534f; - color: white; -} - -a.panel-link{ - text-decoration: none; - color:#333333; -} - -a.panel-link:hover .panel-heading{ - background:#dddddd; -} -a.panel-link:hover .panel-body{ - background: #999999; - color:white; -} -a.panel-link:hover .panel{ - border:1px solid #bbbbbb; -} -a.panel-link .panel.selected .panel-heading, -a.panel-link .panel.selected .panel-body, -li.selected a{ - background: #f9dd56; -} - -a.panel-link .panel.selected { - border:1px solid #f9bc56; -} -.paginator{ - text-align: center; -} - -ul.pagination{ - clear: both; - margin:0; -} -ul.pagination li a{ - min-width: 40px; - padding: 7px 2px; -} -.animate-enter, -.animate-leave { - -webkit-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; - -moz-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; - -ms-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; - -o-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; - transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; - position: relative; - display: block; -} - -.animate-leave.animate-leave-active, -.animate-enter { - -webkit-transform: scaleY(0); - -moz-transform: scaleY(0); - -ms-transform: scaleY(0); - -o-transform: scaleY(0); - transform: scaleY(0); - height: 0px; - opacity: 0; -} - -.animate-enter.animate-enter-active, -.animate-leave { - -webkit-transform: scaleY(1); - -moz-transform: scaleY(1); - -ms-transform: scaleY(1); - -o-transform: scaleY(1); - transform: scaleY(1); - height: 30px; - opacity: 1; -} - - - -/* icons */ - -.icon24 { - /* height:24px; - width:24px; */ -} - -.bgc01 { - background: #0000DD; -} - -.bgc-default { - background: #a85eca; -} - -.bgc-new { - background: #32cd32; -} - -.bgc-accepted { - background: #4169e1; -} - -.bgc-expired { - background: grey; -} - -.bgc-done { - background: #cd853f; -} - -.bgc-invalid { - background: #ff4500; -} - -.bgc-new-accepted { - background: #32cd32; /* Old browsers */ - background: -moz-linear-gradient(-45deg, #32cd32 50%, #4169e1 50%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, right bottom, color-stop(50%,#32cd32), color-stop(50%,#4169e1)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(-45deg, #32cd32 50%,#4169e1 50%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(-45deg, #32cd32 50%,#4169e1 50%); /* Opera 11.10+ */ - background: -ms-linear-gradient(-45deg, #32cd32 50%,#4169e1 50%); /* IE10+ */ - background: linear-gradient(135deg, #32cd32 50%,#4169e1 50%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#32cd32', endColorstr='#4169e1',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ -} - - .round-corner { - -webkit-border-radius: 3px 3px 3px 3px; - -moz-border-radius: 3px 3px 3px 3px; - -o-border-radius: 3px 3px 3px 3px; - border-radius: 3px 3px 3px 3px; - } - -.bgc-accepted-done { - background: #4169e1; /* Old browsers */ - background: -moz-linear-gradient(-45deg, #4169e1 50%, #cd853f 50%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, right bottom, color-stop(50%,#4169e1), color-stop(50%,#cd853f)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(-45deg, #4169e1 50%,#cd853f 50%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(-45deg, #4169e1 50%,#cd853f 50%); /* Opera 11.10+ */ - background: -ms-linear-gradient(-45deg, #4169e1 50%,#cd853f 50%); /* IE10+ */ - background: linear-gradient(135deg, #4169e1 50%,#cd853f 50%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4169e1', endColorstr='#cd853f',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ -} - -.bgc-new-done { - background: #32cd32; /* Old browsers */ - background: -moz-linear-gradient(-45deg, #32cd32 50%, #cd853f 50%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, right bottom, color-stop(50%,#32cd32), color-stop(50%,#cd853f)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(-45deg, #32cd32 50%,#cd853f 50%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(-45deg, #32cd32 50%,#cd853f 50%); /* Opera 11.10+ */ - background: -ms-linear-gradient(-45deg, #32cd32 50%,#cd853f 50%); /* IE10+ */ - background: linear-gradient(135deg, #32cd32 50%,#cd853f 50%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#32cd32', endColorstr='#cd853f',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ -} - -.bgc-horizontal { - background: #ff3236; /* Old browsers */ - background: -moz-linear-gradient(left, #ff3236 50%, #7db9e8 50%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, right top, color-stop(50%,#ff3236), color-stop(50%,#7db9e8)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(left, #ff3236 50%,#7db9e8 50%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(left, #ff3236 50%,#7db9e8 50%); /* Opera 11.10+ */ - background: -ms-linear-gradient(left, #ff3236 50%,#7db9e8 50%); /* IE10+ */ - background: linear-gradient(to right, #ff3236 50%,#7db9e8 50%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff3236', endColorstr='#7db9e8',GradientType=1 ); /* IE6-9 */ -} - -.bgc-vertical { - background: #ff3236; /* Old browsers */ - background: -moz-linear-gradient(top, #ff3236 50%, #7db9e8 50%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(50%,#ff3236), color-stop(50%,#7db9e8)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ff3236 50%,#7db9e8 50%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #ff3236 50%,#7db9e8 50%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, #ff3236 50%,#7db9e8 50%); /* IE10+ */ - background: linear-gradient(to bottom, #ff3236 50%,#7db9e8 50%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff3236', endColorstr='#7db9e8',GradientType=0 ); /* IE6-9 */ -} - -/* qrcode */ - -.qrcode-address { - height: 145px; -} - -.btc-tbl-btn { - margin-left: 8px; -} - -td.captionTd1 { - width: 62px; -} diff --git a/www/css/bootstrap.css b/www/css/bootstrap.css deleted file mode 100644 index bbda4ee..0000000 --- a/www/css/bootstrap.css +++ /dev/null @@ -1,6805 +0,0 @@ -/*! - * Bootstrap v3.0.0 - * - * Copyright 2013 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. - */ - -/*! normalize.css v2.1.0 | MIT License | git.io/normalize */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -audio, -canvas, -video { - display: inline-block; -} - -audio:not([controls]) { - display: none; - height: 0; -} - -[hidden] { - display: none; -} - -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - margin: 0; -} - -a:focus { - outline: thin dotted; -} - -a:active, -a:hover { - outline: 0; -} - -h1 { - margin: 0.67em 0; - font-size: 2em; -} - -abbr[title] { - border-bottom: 1px dotted; -} - -b, -strong { - font-weight: bold; -} - -dfn { - font-style: italic; -} - -hr { - height: 0; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -mark { - color: #000; - background: #ff0; -} - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -pre { - white-space: pre-wrap; -} - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -small { - font-size: 80%; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - border: 0; -} - -svg:not(:root) { - overflow: hidden; -} - -figure { - margin: 0; -} - -fieldset { - padding: 0.35em 0.625em 0.75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} - -legend { - padding: 0; - border: 0; -} - -button, -input, -select, -textarea { - margin: 0; - font-family: inherit; - font-size: 100%; -} - -button, -input { - line-height: normal; -} - -button, -select { - text-transform: none; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -button[disabled], -html input[disabled] { - cursor: default; -} - -input[type="checkbox"], -input[type="radio"] { - padding: 0; - box-sizing: border-box; -} - -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-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -@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: 2cm .5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} - -*, -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -html { - font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.428571429; - color: #333333; - background-color: #ffffff; -} - -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -button, -input, -select[multiple], -textarea { - background-image: none; -} - -a { - color: #428bca; - text-decoration: none; -} - -a:hover, -a:focus { - color: #2a6496; - text-decoration: underline; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -img { - vertical-align: middle; -} - -.img-responsive { - display: block; - height: auto; - max-width: 100%; -} - -.img-rounded { - border-radius: 6px; -} - -.img-thumbnail { - display: inline-block; - height: auto; - max-width: 100%; - padding: 4px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.img-circle { - border-radius: 50%; -} - -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eeeeee; -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0 0 0 0); - border: 0; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 16.099999999999998px; - font-weight: 200; - line-height: 1.4; -} - -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} - -small { - font-size: 85%; -} - -cite { - font-style: normal; -} - -.text-muted { - color: #999999; -} - -.text-primary { - color: #428bca; -} - -.text-warning { - color: #c09853; -} - -.text-danger { - color: #b94a48; -} - -.text-success { - color: #468847; -} - -.text-info { - color: #3a87ad; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 500; - line-height: 1.1; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - margin-top: 20px; - margin-bottom: 10px; -} - -h4, -h5, -h6 { - margin-top: 10px; - margin-bottom: 10px; -} - -h1, -.h1 { - font-size: 36px; -} - -h2, -.h2 { - font-size: 30px; -} - -h3, -.h3 { - font-size: 24px; -} - -h4, -.h4 { - font-size: 18px; -} - -h5, -.h5 { - font-size: 14px; -} - -h6, -.h6 { - font-size: 12px; -} - -h1 small, -.h1 small { - font-size: 24px; -} - -h2 small, -.h2 small { - font-size: 18px; -} - -h3 small, -.h3 small, -h4 small, -.h4 small { - font-size: 14px; -} - -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} - -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} - -.list-unstyled { - padding-left: 0; - list-style: none; -} - -.list-inline { - padding-left: 0; - list-style: none; -} - -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} - -dl { - margin-bottom: 20px; -} - -dt, -dd { - line-height: 1.428571429; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 0; -} - -@media (min-width: 768px) { - .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; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - display: table; - content: " "; - } - .dl-horizontal dd:after { - clear: both; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - display: table; - content: " "; - } - .dl-horizontal dd:after { - clear: both; - } -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote p:last-child { - margin-bottom: 0; -} - -blockquote small { - display: block; - line-height: 1.428571429; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-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: 1.428571429; -} - -code, -pre { - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; -} - -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - white-space: nowrap; - background-color: #f9f2f4; - border-radius: 4px; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.428571429; - color: #333333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #cccccc; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 20px; -} - -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -.container:before, -.container:after { - display: table; - content: " "; -} - -.container:after { - clear: both; -} - -.container:before, -.container:after { - display: table; - content: " "; -} - -.container:after { - clear: both; -} - -.row { - margin-right: -15px; - margin-left: -15px; -} - -.row:before, -.row:after { - display: table; - content: " "; -} - -.row:after { - clear: both; -} - -.row:before, -.row:after { - display: table; - content: " "; -} - -.row:after { - clear: both; -} - -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11, -.col-xs-12, -.col-sm-1, -.col-sm-2, -.col-sm-3, -.col-sm-4, -.col-sm-5, -.col-sm-6, -.col-sm-7, -.col-sm-8, -.col-sm-9, -.col-sm-10, -.col-sm-11, -.col-sm-12, -.col-md-1, -.col-md-2, -.col-md-3, -.col-md-4, -.col-md-5, -.col-md-6, -.col-md-7, -.col-md-8, -.col-md-9, -.col-md-10, -.col-md-11, -.col-md-12, -.col-lg-1, -.col-lg-2, -.col-lg-3, -.col-lg-4, -.col-lg-5, -.col-lg-6, -.col-lg-7, -.col-lg-8, -.col-lg-9, -.col-lg-10, -.col-lg-11, -.col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} - -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11 { - float: left; -} - -.col-xs-1 { - width: 8.333333333333332%; -} - -.col-xs-2 { - width: 16.666666666666664%; -} - -.col-xs-3 { - width: 25%; -} - -.col-xs-4 { - width: 33.33333333333333%; -} - -.col-xs-5 { - width: 41.66666666666667%; -} - -.col-xs-6 { - width: 50%; -} - -.col-xs-7 { - width: 58.333333333333336%; -} - -.col-xs-8 { - width: 66.66666666666666%; -} - -.col-xs-9 { - width: 75%; -} - -.col-xs-10 { - width: 83.33333333333334%; -} - -.col-xs-11 { - width: 91.66666666666666%; -} - -.col-xs-12 { - width: 100%; -} - -@media (min-width: 768px) { - .container { - max-width: 750px; - } - .col-sm-1, - .col-sm-2, - .col-sm-3, - .col-sm-4, - .col-sm-5, - .col-sm-6, - .col-sm-7, - .col-sm-8, - .col-sm-9, - .col-sm-10, - .col-sm-11 { - float: left; - } - .col-sm-1 { - width: 8.333333333333332%; - } - .col-sm-2 { - width: 16.666666666666664%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-4 { - width: 33.33333333333333%; - } - .col-sm-5 { - width: 41.66666666666667%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-7 { - width: 58.333333333333336%; - } - .col-sm-8 { - width: 66.66666666666666%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-10 { - width: 83.33333333333334%; - } - .col-sm-11 { - width: 91.66666666666666%; - } - .col-sm-12 { - width: 100%; - } - .col-sm-push-1 { - left: 8.333333333333332%; - } - .col-sm-push-2 { - left: 16.666666666666664%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-4 { - left: 33.33333333333333%; - } - .col-sm-push-5 { - left: 41.66666666666667%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-7 { - left: 58.333333333333336%; - } - .col-sm-push-8 { - left: 66.66666666666666%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-10 { - left: 83.33333333333334%; - } - .col-sm-push-11 { - left: 91.66666666666666%; - } - .col-sm-pull-1 { - right: 8.333333333333332%; - } - .col-sm-pull-2 { - right: 16.666666666666664%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-4 { - right: 33.33333333333333%; - } - .col-sm-pull-5 { - right: 41.66666666666667%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-7 { - right: 58.333333333333336%; - } - .col-sm-pull-8 { - right: 66.66666666666666%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-10 { - right: 83.33333333333334%; - } - .col-sm-pull-11 { - right: 91.66666666666666%; - } - .col-sm-offset-1 { - margin-left: 8.333333333333332%; - } - .col-sm-offset-2 { - margin-left: 16.666666666666664%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-4 { - margin-left: 33.33333333333333%; - } - .col-sm-offset-5 { - margin-left: 41.66666666666667%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-7 { - margin-left: 58.333333333333336%; - } - .col-sm-offset-8 { - margin-left: 66.66666666666666%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-10 { - margin-left: 83.33333333333334%; - } - .col-sm-offset-11 { - margin-left: 91.66666666666666%; - } -} - -@media (min-width: 992px) { - .container { - max-width: 970px; - } - .col-md-1, - .col-md-2, - .col-md-3, - .col-md-4, - .col-md-5, - .col-md-6, - .col-md-7, - .col-md-8, - .col-md-9, - .col-md-10, - .col-md-11 { - float: left; - } - .col-md-1 { - width: 8.333333333333332%; - } - .col-md-2 { - width: 16.666666666666664%; - } - .col-md-3 { - width: 25%; - } - .col-md-4 { - width: 33.33333333333333%; - } - .col-md-5 { - width: 41.66666666666667%; - } - .col-md-6 { - width: 50%; - } - .col-md-7 { - width: 58.333333333333336%; - } - .col-md-8 { - width: 66.66666666666666%; - } - .col-md-9 { - width: 75%; - } - .col-md-10 { - width: 83.33333333333334%; - } - .col-md-11 { - width: 91.66666666666666%; - } - .col-md-12 { - width: 100%; - } - .col-md-push-0 { - left: auto; - } - .col-md-push-1 { - left: 8.333333333333332%; - } - .col-md-push-2 { - left: 16.666666666666664%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-4 { - left: 33.33333333333333%; - } - .col-md-push-5 { - left: 41.66666666666667%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-7 { - left: 58.333333333333336%; - } - .col-md-push-8 { - left: 66.66666666666666%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-10 { - left: 83.33333333333334%; - } - .col-md-push-11 { - left: 91.66666666666666%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-pull-1 { - right: 8.333333333333332%; - } - .col-md-pull-2 { - right: 16.666666666666664%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-4 { - right: 33.33333333333333%; - } - .col-md-pull-5 { - right: 41.66666666666667%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-7 { - right: 58.333333333333336%; - } - .col-md-pull-8 { - right: 66.66666666666666%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-10 { - right: 83.33333333333334%; - } - .col-md-pull-11 { - right: 91.66666666666666%; - } - .col-md-offset-0 { - margin-left: 0; - } - .col-md-offset-1 { - margin-left: 8.333333333333332%; - } - .col-md-offset-2 { - margin-left: 16.666666666666664%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-4 { - margin-left: 33.33333333333333%; - } - .col-md-offset-5 { - margin-left: 41.66666666666667%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-7 { - margin-left: 58.333333333333336%; - } - .col-md-offset-8 { - margin-left: 66.66666666666666%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-10 { - margin-left: 83.33333333333334%; - } - .col-md-offset-11 { - margin-left: 91.66666666666666%; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1170px; - } - .col-lg-1, - .col-lg-2, - .col-lg-3, - .col-lg-4, - .col-lg-5, - .col-lg-6, - .col-lg-7, - .col-lg-8, - .col-lg-9, - .col-lg-10, - .col-lg-11 { - float: left; - } - .col-lg-1 { - width: 8.333333333333332%; - } - .col-lg-2 { - width: 16.666666666666664%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-4 { - width: 33.33333333333333%; - } - .col-lg-5 { - width: 41.66666666666667%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-7 { - width: 58.333333333333336%; - } - .col-lg-8 { - width: 66.66666666666666%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-10 { - width: 83.33333333333334%; - } - .col-lg-11 { - width: 91.66666666666666%; - } - .col-lg-12 { - width: 100%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-push-1 { - left: 8.333333333333332%; - } - .col-lg-push-2 { - left: 16.666666666666664%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-4 { - left: 33.33333333333333%; - } - .col-lg-push-5 { - left: 41.66666666666667%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-7 { - left: 58.333333333333336%; - } - .col-lg-push-8 { - left: 66.66666666666666%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-10 { - left: 83.33333333333334%; - } - .col-lg-push-11 { - left: 91.66666666666666%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-pull-1 { - right: 8.333333333333332%; - } - .col-lg-pull-2 { - right: 16.666666666666664%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-4 { - right: 33.33333333333333%; - } - .col-lg-pull-5 { - right: 41.66666666666667%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-7 { - right: 58.333333333333336%; - } - .col-lg-pull-8 { - right: 66.66666666666666%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-10 { - right: 83.33333333333334%; - } - .col-lg-pull-11 { - right: 91.66666666666666%; - } - .col-lg-offset-0 { - margin-left: 0; - } - .col-lg-offset-1 { - margin-left: 8.333333333333332%; - } - .col-lg-offset-2 { - margin-left: 16.666666666666664%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-4 { - margin-left: 33.33333333333333%; - } - .col-lg-offset-5 { - margin-left: 41.66666666666667%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-7 { - margin-left: 58.333333333333336%; - } - .col-lg-offset-8 { - margin-left: 66.66666666666666%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-10 { - margin-left: 83.33333333333334%; - } - .col-lg-offset-11 { - margin-left: 91.66666666666666%; - } -} - -table { - max-width: 100%; - background-color: transparent; -} - -th { - text-align: left; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table thead > tr > th, -.table tbody > tr > th, -.table tfoot > tr > th, -.table thead > tr > td, -.table tbody > tr > td, -.table tfoot > tr > td { - padding: 8px; - line-height: 1.428571429; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #dddddd; -} - -.table caption + thead tr:first-child th, -.table colgroup + thead tr:first-child th, -.table thead:first-child tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child td, -.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 thead > tr > th, -.table-condensed tbody > tr > th, -.table-condensed tfoot > tr > th, -.table-condensed thead > tr > td, -.table-condensed tbody > tr > td, -.table-condensed tfoot > tr > td { - padding: 5px; -} - -.table-bordered { - border: 1px solid #dddddd; -} - -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #dddddd; -} - -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} - -.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 col[class*="col-"] { - display: table-column; - float: none; -} - -table td[class*="col-"], -table th[class*="col-"] { - display: table-cell; - float: none; -} - -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} - -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td { - background-color: #d0e9c6; - border-color: #c9e2b3; -} - -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; - border-color: #eed3d7; -} - -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td { - background-color: #ebcccc; - border-color: #e6c1c7; -} - -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; - border-color: #fbeed5; -} - -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td { - background-color: #faf2cc; - border-color: #f8e5be; -} - -@media (max-width: 768px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-x: scroll; - overflow-y: hidden; - border: 1px solid #dddddd; - } - .table-responsive > .table { - margin-bottom: 0; - background-color: #fff; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > thead > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > thead > tr:last-child > td, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; -} - -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - /* IE8-9 */ - - line-height: normal; -} - -input[type="file"] { - display: block; -} - -select[multiple], -select[size] { - height: auto; -} - -select optgroup { - font-family: inherit; - font-size: inherit; - font-style: inherit; -} - -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; -} - -input[type="number"]::-webkit-outer-spin-button, -input[type="number"]::-webkit-inner-spin-button { - height: auto; -} - -.form-control:-moz-placeholder { - color: #999999; -} - -.form-control::-moz-placeholder { - color: #999999; -} - -.form-control:-ms-input-placeholder { - color: #999999; -} - -.form-control::-webkit-input-placeholder { - color: #999999; -} - -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.428571429; - color: #555555; - vertical-align: middle; - background-color: #ffffff; - border: 1px solid #cccccc; - border-radius: 4px; - -webkit-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-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; - transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; -} - -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); -} - -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #eeeeee; -} - -textarea.form-control { - height: auto; -} - -.form-group { - margin-bottom: 15px; -} - -.radio, -.checkbox { - display: block; - min-height: 20px; - padding-left: 20px; - margin-top: 10px; - margin-bottom: 10px; - vertical-align: middle; -} - -.radio label, -.checkbox label { - display: inline; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} - -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} - -.radio-inline, -.checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} - -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -.radio[disabled], -.radio-inline[disabled], -.checkbox[disabled], -.checkbox-inline[disabled], -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"], -fieldset[disabled] .radio, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} - -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -select.input-sm { - height: 30px; - line-height: 30px; -} - -textarea.input-sm { - height: auto; -} - -.input-lg { - height: 45px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -select.input-lg { - height: 45px; - line-height: 45px; -} - -textarea.input-lg { - height: auto; -} - -.has-warning .help-block, -.has-warning .control-label { - color: #c09853; -} - -.has-warning .form-control { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-warning .form-control:focus { - border-color: #a47e3c; - -webkit-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; -} - -.has-warning .input-group-addon { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.has-error .help-block, -.has-error .control-label { - color: #b94a48; -} - -.has-error .form-control { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-error .form-control:focus { - border-color: #953b39; - -webkit-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; -} - -.has-error .input-group-addon { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.has-success .help-block, -.has-success .control-label { - color: #468847; -} - -.has-success .form-control { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-success .form-control:focus { - border-color: #356635; - -webkit-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; -} - -.has-success .input-group-addon { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -.form-control-static { - padding-top: 7px; - margin-bottom: 0; -} - -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} - -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} - -.form-horizontal .control-label, -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} - -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} - -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - display: table; - content: " "; -} - -.form-horizontal .form-group:after { - clear: both; -} - -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - display: table; - content: " "; -} - -.form-horizontal .form-group:after { - clear: both; -} - -@media (min-width: 768px) { - .form-horizontal .control-label { - text-align: right; - } -} - -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.428571429; - text-align: center; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - border: 1px solid transparent; - border-radius: 4px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; -} - -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} - -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; -} - -.btn-default { - color: #333333; - background-color: #ffffff; - border-color: #cccccc; -} - -.btn-default:hover, -.btn-default:focus, -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - color: #333333; - background-color: #ebebeb; - border-color: #adadad; -} - -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - background-image: none; -} - -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #ffffff; - border-color: #cccccc; -} - -.btn-primary { - color: #ffffff; - background-color: #428bca; - border-color: #357ebd; -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - color: #ffffff; - background-color: #3276b1; - border-color: #285e8e; -} - -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - background-image: none; -} - -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; -} - -.btn-warning { - color: #ffffff; - background-color: #f0ad4e; - border-color: #eea236; -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - color: #ffffff; - background-color: #ed9c28; - border-color: #d58512; -} - -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - background-image: none; -} - -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; -} - -.btn-danger { - color: #ffffff; - background-color: #d9534f; - border-color: #d43f3a; -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - color: #ffffff; - background-color: #d2322d; - border-color: #ac2925; -} - -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - background-image: none; -} - -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; -} - -.btn-success { - color: #ffffff; - background-color: #5cb85c; - border-color: #4cae4c; -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - color: #ffffff; - background-color: #47a447; - border-color: #398439; -} - -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - background-image: none; -} - -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; -} - -.btn-info { - color: #ffffff; - background-color: #5bc0de; - border-color: #46b8da; -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - color: #ffffff; - background-color: #39b3d7; - border-color: #269abc; -} - -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - background-image: none; -} - -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; -} - -.btn-link { - font-weight: normal; - color: #428bca; - cursor: pointer; - border-radius: 0; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} - -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} - -.btn-link:hover, -.btn-link:focus { - color: #2a6496; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #999999; - text-decoration: none; -} - -.btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -.btn-sm, -.btn-xs { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-xs { - padding: 1px 5px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - display: none; -} - -.collapse.in { - display: block; -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -@font-face { - font-family: 'Glyphicons Halflings'; - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); -} - -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - -webkit-font-smoothing: antialiased; - font-style: normal; - font-weight: normal; - line-height: 1; -} - -.glyphicon-asterisk:before { - content: "\2a"; -} - -.glyphicon-plus:before { - content: "\2b"; -} - -.glyphicon-euro:before { - content: "\20ac"; -} - -.glyphicon-minus:before { - content: "\2212"; -} - -.glyphicon-cloud:before { - content: "\2601"; -} - -.glyphicon-envelope:before { - content: "\2709"; -} - -.glyphicon-pencil:before { - content: "\270f"; -} - -.glyphicon-glass:before { - content: "\e001"; -} - -.glyphicon-music:before { - content: "\e002"; -} - -.glyphicon-search:before { - content: "\e003"; -} - -.glyphicon-heart:before { - content: "\e005"; -} - -.glyphicon-star:before { - content: "\e006"; -} - -.glyphicon-star-empty:before { - content: "\e007"; -} - -.glyphicon-user:before { - content: "\e008"; -} - -.glyphicon-film:before { - content: "\e009"; -} - -.glyphicon-th-large:before { - content: "\e010"; -} - -.glyphicon-th:before { - content: "\e011"; -} - -.glyphicon-th-list:before { - content: "\e012"; -} - -.glyphicon-ok:before { - content: "\e013"; -} - -.glyphicon-remove:before { - content: "\e014"; -} - -.glyphicon-zoom-in:before { - content: "\e015"; -} - -.glyphicon-zoom-out:before { - content: "\e016"; -} - -.glyphicon-off:before { - content: "\e017"; -} - -.glyphicon-signal:before { - content: "\e018"; -} - -.glyphicon-cog:before { - content: "\e019"; -} - -.glyphicon-trash:before { - content: "\e020"; -} - -.glyphicon-home:before { - content: "\e021"; -} - -.glyphicon-file:before { - content: "\e022"; -} - -.glyphicon-time:before { - content: "\e023"; -} - -.glyphicon-road:before { - content: "\e024"; -} - -.glyphicon-download-alt:before { - content: "\e025"; -} - -.glyphicon-download:before { - content: "\e026"; -} - -.glyphicon-upload:before { - content: "\e027"; -} - -.glyphicon-inbox:before { - content: "\e028"; -} - -.glyphicon-play-circle:before { - content: "\e029"; -} - -.glyphicon-repeat:before { - content: "\e030"; -} - -.glyphicon-refresh:before { - content: "\e031"; -} - -.glyphicon-list-alt:before { - content: "\e032"; -} - -.glyphicon-flag:before { - content: "\e034"; -} - -.glyphicon-headphones:before { - content: "\e035"; -} - -.glyphicon-volume-off:before { - content: "\e036"; -} - -.glyphicon-volume-down:before { - content: "\e037"; -} - -.glyphicon-volume-up:before { - content: "\e038"; -} - -.glyphicon-qrcode:before { - content: "\e039"; -} - -.glyphicon-barcode:before { - content: "\e040"; -} - -.glyphicon-tag:before { - content: "\e041"; -} - -.glyphicon-tags:before { - content: "\e042"; -} - -.glyphicon-book:before { - content: "\e043"; -} - -.glyphicon-print:before { - content: "\e045"; -} - -.glyphicon-font:before { - content: "\e047"; -} - -.glyphicon-bold:before { - content: "\e048"; -} - -.glyphicon-italic:before { - content: "\e049"; -} - -.glyphicon-text-height:before { - content: "\e050"; -} - -.glyphicon-text-width:before { - content: "\e051"; -} - -.glyphicon-align-left:before { - content: "\e052"; -} - -.glyphicon-align-center:before { - content: "\e053"; -} - -.glyphicon-align-right:before { - content: "\e054"; -} - -.glyphicon-align-justify:before { - content: "\e055"; -} - -.glyphicon-list:before { - content: "\e056"; -} - -.glyphicon-indent-left:before { - content: "\e057"; -} - -.glyphicon-indent-right:before { - content: "\e058"; -} - -.glyphicon-facetime-video:before { - content: "\e059"; -} - -.glyphicon-picture:before { - content: "\e060"; -} - -.glyphicon-map-marker:before { - content: "\e062"; -} - -.glyphicon-adjust:before { - content: "\e063"; -} - -.glyphicon-tint:before { - content: "\e064"; -} - -.glyphicon-edit:before { - content: "\e065"; -} - -.glyphicon-share:before { - content: "\e066"; -} - -.glyphicon-check:before { - content: "\e067"; -} - -.glyphicon-move:before { - content: "\e068"; -} - -.glyphicon-step-backward:before { - content: "\e069"; -} - -.glyphicon-fast-backward:before { - content: "\e070"; -} - -.glyphicon-backward:before { - content: "\e071"; -} - -.glyphicon-play:before { - content: "\e072"; -} - -.glyphicon-pause:before { - content: "\e073"; -} - -.glyphicon-stop:before { - content: "\e074"; -} - -.glyphicon-forward:before { - content: "\e075"; -} - -.glyphicon-fast-forward:before { - content: "\e076"; -} - -.glyphicon-step-forward:before { - content: "\e077"; -} - -.glyphicon-eject:before { - content: "\e078"; -} - -.glyphicon-chevron-left:before { - content: "\e079"; -} - -.glyphicon-chevron-right:before { - content: "\e080"; -} - -.glyphicon-plus-sign:before { - content: "\e081"; -} - -.glyphicon-minus-sign:before { - content: "\e082"; -} - -.glyphicon-remove-sign:before { - content: "\e083"; -} - -.glyphicon-ok-sign:before { - content: "\e084"; -} - -.glyphicon-question-sign:before { - content: "\e085"; -} - -.glyphicon-info-sign:before { - content: "\e086"; -} - -.glyphicon-screenshot:before { - content: "\e087"; -} - -.glyphicon-remove-circle:before { - content: "\e088"; -} - -.glyphicon-ok-circle:before { - content: "\e089"; -} - -.glyphicon-ban-circle:before { - content: "\e090"; -} - -.glyphicon-arrow-left:before { - content: "\e091"; -} - -.glyphicon-arrow-right:before { - content: "\e092"; -} - -.glyphicon-arrow-up:before { - content: "\e093"; -} - -.glyphicon-arrow-down:before { - content: "\e094"; -} - -.glyphicon-share-alt:before { - content: "\e095"; -} - -.glyphicon-resize-full:before { - content: "\e096"; -} - -.glyphicon-resize-small:before { - content: "\e097"; -} - -.glyphicon-exclamation-sign:before { - content: "\e101"; -} - -.glyphicon-gift:before { - content: "\e102"; -} - -.glyphicon-leaf:before { - content: "\e103"; -} - -.glyphicon-eye-open:before { - content: "\e105"; -} - -.glyphicon-eye-close:before { - content: "\e106"; -} - -.glyphicon-warning-sign:before { - content: "\e107"; -} - -.glyphicon-plane:before { - content: "\e108"; -} - -.glyphicon-random:before { - content: "\e110"; -} - -.glyphicon-comment:before { - content: "\e111"; -} - -.glyphicon-magnet:before { - content: "\e112"; -} - -.glyphicon-chevron-up:before { - content: "\e113"; -} - -.glyphicon-chevron-down:before { - content: "\e114"; -} - -.glyphicon-retweet:before { - content: "\e115"; -} - -.glyphicon-shopping-cart:before { - content: "\e116"; -} - -.glyphicon-folder-close:before { - content: "\e117"; -} - -.glyphicon-folder-open:before { - content: "\e118"; -} - -.glyphicon-resize-vertical:before { - content: "\e119"; -} - -.glyphicon-resize-horizontal:before { - content: "\e120"; -} - -.glyphicon-hdd:before { - content: "\e121"; -} - -.glyphicon-bullhorn:before { - content: "\e122"; -} - -.glyphicon-certificate:before { - content: "\e124"; -} - -.glyphicon-thumbs-up:before { - content: "\e125"; -} - -.glyphicon-thumbs-down:before { - content: "\e126"; -} - -.glyphicon-hand-right:before { - content: "\e127"; -} - -.glyphicon-hand-left:before { - content: "\e128"; -} - -.glyphicon-hand-up:before { - content: "\e129"; -} - -.glyphicon-hand-down:before { - content: "\e130"; -} - -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} - -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} - -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} - -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} - -.glyphicon-globe:before { - content: "\e135"; -} - -.glyphicon-tasks:before { - content: "\e137"; -} - -.glyphicon-filter:before { - content: "\e138"; -} - -.glyphicon-fullscreen:before { - content: "\e140"; -} - -.glyphicon-dashboard:before { - content: "\e141"; -} - -.glyphicon-heart-empty:before { - content: "\e143"; -} - -.glyphicon-link:before { - content: "\e144"; -} - -.glyphicon-phone:before { - content: "\e145"; -} - -.glyphicon-usd:before { - content: "\e148"; -} - -.glyphicon-gbp:before { - content: "\e149"; -} - -.glyphicon-sort:before { - content: "\e150"; -} - -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} - -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} - -.glyphicon-sort-by-order:before { - content: "\e153"; -} - -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} - -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} - -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} - -.glyphicon-unchecked:before { - content: "\e157"; -} - -.glyphicon-expand:before { - content: "\e158"; -} - -.glyphicon-collapse-down:before { - content: "\e159"; -} - -.glyphicon-collapse-up:before { - content: "\e160"; -} - -.glyphicon-log-in:before { - content: "\e161"; -} - -.glyphicon-flash:before { - content: "\e162"; -} - -.glyphicon-log-out:before { - content: "\e163"; -} - -.glyphicon-new-window:before { - content: "\e164"; -} - -.glyphicon-record:before { - content: "\e165"; -} - -.glyphicon-save:before { - content: "\e166"; -} - -.glyphicon-open:before { - content: "\e167"; -} - -.glyphicon-saved:before { - content: "\e168"; -} - -.glyphicon-import:before { - content: "\e169"; -} - -.glyphicon-export:before { - content: "\e170"; -} - -.glyphicon-send:before { - content: "\e171"; -} - -.glyphicon-floppy-disk:before { - content: "\e172"; -} - -.glyphicon-floppy-saved:before { - content: "\e173"; -} - -.glyphicon-floppy-remove:before { - content: "\e174"; -} - -.glyphicon-floppy-save:before { - content: "\e175"; -} - -.glyphicon-floppy-open:before { - content: "\e176"; -} - -.glyphicon-credit-card:before { - content: "\e177"; -} - -.glyphicon-transfer:before { - content: "\e178"; -} - -.glyphicon-cutlery:before { - content: "\e179"; -} - -.glyphicon-header:before { - content: "\e180"; -} - -.glyphicon-compressed:before { - content: "\e181"; -} - -.glyphicon-earphone:before { - content: "\e182"; -} - -.glyphicon-phone-alt:before { - content: "\e183"; -} - -.glyphicon-tower:before { - content: "\e184"; -} - -.glyphicon-stats:before { - content: "\e185"; -} - -.glyphicon-sd-video:before { - content: "\e186"; -} - -.glyphicon-hd-video:before { - content: "\e187"; -} - -.glyphicon-subtitles:before { - content: "\e188"; -} - -.glyphicon-sound-stereo:before { - content: "\e189"; -} - -.glyphicon-sound-dolby:before { - content: "\e190"; -} - -.glyphicon-sound-5-1:before { - content: "\e191"; -} - -.glyphicon-sound-6-1:before { - content: "\e192"; -} - -.glyphicon-sound-7-1:before { - content: "\e193"; -} - -.glyphicon-copyright-mark:before { - content: "\e194"; -} - -.glyphicon-registration-mark:before { - content: "\e195"; -} - -.glyphicon-cloud-download:before { - content: "\e197"; -} - -.glyphicon-cloud-upload:before { - content: "\e198"; -} - -.glyphicon-tree-conifer:before { - content: "\e199"; -} - -.glyphicon-tree-deciduous:before { - content: "\e200"; -} - -.glyphicon-briefcase:before { - content: "\1f4bc"; -} - -.glyphicon-calendar:before { - content: "\1f4c5"; -} - -.glyphicon-pushpin:before { - content: "\1f4cc"; -} - -.glyphicon-paperclip:before { - content: "\1f4ce"; -} - -.glyphicon-camera:before { - content: "\1f4f7"; -} - -.glyphicon-lock:before { - content: "\1f512"; -} - -.glyphicon-bell:before { - content: "\1f514"; -} - -.glyphicon-bookmark:before { - content: "\1f516"; -} - -.glyphicon-fire:before { - content: "\1f525"; -} - -.glyphicon-wrench:before { - content: "\1f527"; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-bottom: 0 dotted; - border-left: 4px solid transparent; - content: ""; -} - -.dropdown { - position: relative; -} - -.dropdown-toggle:focus { - outline: 0; -} - -.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; - font-size: 14px; - list-style: none; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.428571429; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #428bca; -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #428bca; - outline: 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: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open > .dropdown-menu { - display: block; -} - -.open > a { - outline: 0; -} - -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.428571429; - color: #999999; -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0 dotted; - border-bottom: 4px solid #000000; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } -} - -.btn-default .caret { - border-top-color: #333333; -} - -.btn-primary .caret, -.btn-success .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret { - border-top-color: #fff; -} - -.dropup .btn-default .caret { - border-bottom-color: #333333; -} - -.dropup .btn-primary .caret, -.dropup .btn-success .caret, -.dropup .btn-warning .caret, -.dropup .btn-danger .caret, -.dropup .btn-info .caret { - border-bottom-color: #fff; -} - -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} - -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} - -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} - -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus { - outline: none; -} - -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} - -.btn-toolbar:before, -.btn-toolbar:after { - display: table; - content: " "; -} - -.btn-toolbar:after { - clear: both; -} - -.btn-toolbar:before, -.btn-toolbar:after { - display: table; - content: " "; -} - -.btn-toolbar:after { - clear: both; -} - -.btn-toolbar .btn-group { - float: left; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group, -.btn-toolbar > .btn-group + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} - -.btn-group > .btn:first-child { - margin-left: 0; -} - -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.btn-group > .btn-group { - float: left; -} - -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} - -.btn-group > .btn-group:first-child > .btn:last-child, -.btn-group > .btn-group:first-child > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.btn-group > .btn-group:last-child > .btn:first-child { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group-xs > .btn { - padding: 5px 10px; - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} - -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} - -.btn .caret { - margin-left: 0; -} - -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} - -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} - -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group { - display: block; - float: none; - width: 100%; - max-width: 100%; -} - -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - display: table; - content: " "; -} - -.btn-group-vertical > .btn-group:after { - clear: both; -} - -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - display: table; - content: " "; -} - -.btn-group-vertical > .btn-group:after { - clear: both; -} - -.btn-group-vertical > .btn-group > .btn { - float: none; -} - -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} - -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-right-radius: 0; - border-bottom-left-radius: 4px; - border-top-left-radius: 0; -} - -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} - -.btn-group-vertical > .btn-group:first-child > .btn:last-child, -.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group-vertical > .btn-group:last-child > .btn:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.btn-group-justified { - display: table; - width: 100%; - border-collapse: separate; - table-layout: fixed; -} - -.btn-group-justified .btn { - display: table-cell; - float: none; - width: 1%; -} - -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; -} - -.input-group { - position: relative; - display: table; - border-collapse: separate; -} - -.input-group.col { - float: none; - padding-right: 0; - padding-left: 0; -} - -.input-group .form-control { - width: 100%; - margin-bottom: 0; -} - -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 45px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 45px; - line-height: 45px; -} - -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn { - height: auto; -} - -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} - -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn { - height: auto; -} - -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} - -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} - -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} - -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - text-align: center; - background-color: #eeeeee; - border: 1px solid #cccccc; - border-radius: 4px; -} - -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} - -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} - -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} - -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.input-group-addon:first-child { - border-right: 0; -} - -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.input-group-addon:last-child { - border-left: 0; -} - -.input-group-btn { - position: relative; - white-space: nowrap; -} - -.input-group-btn > .btn { - position: relative; -} - -.input-group-btn > .btn + .btn { - margin-left: -4px; -} - -.input-group-btn > .btn:hover, -.input-group-btn > .btn:active { - z-index: 2; -} - -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.nav:before, -.nav:after { - display: table; - content: " "; -} - -.nav:after { - clear: both; -} - -.nav:before, -.nav:after { - display: table; - content: " "; -} - -.nav:after { - clear: both; -} - -.nav > li { - position: relative; - display: block; -} - -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li.disabled > a { - color: #999999; -} - -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #999999; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} - -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eeeeee; - border-color: #428bca; -} - -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} - -.nav > li > a > img { - max-width: none; -} - -.nav-tabs { - border-bottom: 1px solid #dddddd; -} - -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} - -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.428571429; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #dddddd; - border-bottom-color: transparent; -} - -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} - -.nav-tabs.nav-justified > li { - float: none; -} - -.nav-tabs.nav-justified > li > a { - text-align: center; -} - -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } -} - -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-bottom: 1px solid #dddddd; -} - -.nav-tabs.nav-justified > .active > a { - border-bottom-color: #ffffff; -} - -.nav-pills > li { - float: left; -} - -.nav-pills > li > a { - border-radius: 5px; -} - -.nav-pills > li + li { - margin-left: 2px; -} - -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #ffffff; - background-color: #428bca; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} - -.nav-justified { - width: 100%; -} - -.nav-justified > li { - float: none; -} - -.nav-justified > li > a { - text-align: center; -} - -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } -} - -.nav-tabs-justified { - border-bottom: 0; -} - -.nav-tabs-justified > li > a { - margin-right: 0; - border-bottom: 1px solid #dddddd; -} - -.nav-tabs-justified > .active > a { - border-bottom-color: #ffffff; -} - -.tabbable:before, -.tabbable:after { - display: table; - content: " "; -} - -.tabbable:after { - clear: both; -} - -.tabbable:before, -.tabbable:after { - display: table; - content: " "; -} - -.tabbable:after { - clear: both; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.nav .caret { - border-top-color: #428bca; - border-bottom-color: #428bca; -} - -.nav a:hover .caret { - border-top-color: #2a6496; - border-bottom-color: #2a6496; -} - -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.navbar { - position: relative; - z-index: 1000; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} - -.navbar:before, -.navbar:after { - display: table; - content: " "; -} - -.navbar:after { - clear: both; -} - -.navbar:before, -.navbar:after { - display: table; - content: " "; -} - -.navbar:after { - clear: both; -} - -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} - -.navbar-header:before, -.navbar-header:after { - display: table; - content: " "; -} - -.navbar-header:after { - clear: both; -} - -.navbar-header:before, -.navbar-header:after { - display: table; - content: " "; -} - -.navbar-header:after { - clear: both; -} - -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} - -.navbar-collapse { - max-height: 340px; - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - -webkit-overflow-scrolling: touch; -} - -.navbar-collapse:before, -.navbar-collapse:after { - display: table; - content: " "; -} - -.navbar-collapse:after { - clear: both; -} - -.navbar-collapse:before, -.navbar-collapse:after { - display: table; - content: " "; -} - -.navbar-collapse:after { - clear: both; -} - -.navbar-collapse.in { - overflow-y: auto; -} - -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-collapse .navbar-nav.navbar-left:first-child { - margin-left: -15px; - } - .navbar-collapse .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } - .navbar-collapse .navbar-text:last-child { - margin-right: 0; - } -} - -.container > .navbar-header, -.container > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} - -@media (min-width: 768px) { - .container > .navbar-header, - .container > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} - -.navbar-static-top { - border-width: 0 0 1px; -} - -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - border-width: 0 0 1px; -} - -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} - -.navbar-fixed-top { - top: 0; - z-index: 1030; -} - -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; -} - -.navbar-brand { - float: left; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} - -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} - -@media (min-width: 768px) { - .navbar > .container .navbar-brand { - margin-left: -15px; - } -} - -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - border: 1px solid transparent; - border-radius: 4px; -} - -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} - -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} - -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} - -.navbar-nav { - margin: 7.5px -15px; -} - -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} - -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} - -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} - -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } -} - -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-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); -} - -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} - -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } -} - -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} - -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.navbar-nav.pull-right > li > .dropdown-menu, -.navbar-nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} - -.navbar-text { - float: left; - margin-top: 15px; - margin-bottom: 15px; -} - -@media (min-width: 768px) { - .navbar-text { - margin-right: 15px; - margin-left: 15px; - } -} - -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} - -.navbar-default .navbar-brand { - color: #777777; -} - -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} - -.navbar-default .navbar-text { - color: #777777; -} - -.navbar-default .navbar-nav > li > a { - color: #777777; -} - -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333333; - background-color: transparent; -} - -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555555; - background-color: #e7e7e7; -} - -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #cccccc; - background-color: transparent; -} - -.navbar-default .navbar-toggle { - border-color: #dddddd; -} - -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #dddddd; -} - -.navbar-default .navbar-toggle .icon-bar { - background-color: #cccccc; -} - -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e6e6e6; -} - -.navbar-default .navbar-nav > .dropdown > a:hover .caret, -.navbar-default .navbar-nav > .dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555555; - background-color: #e7e7e7; -} - -.navbar-default .navbar-nav > .open > a .caret, -.navbar-default .navbar-nav > .open > a:hover .caret, -.navbar-default .navbar-nav > .open > a:focus .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.navbar-default .navbar-nav > .dropdown > a .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} - -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #cccccc; - background-color: transparent; - } -} - -.navbar-default .navbar-link { - color: #777777; -} - -.navbar-default .navbar-link:hover { - color: #333333; -} - -.navbar-inverse { - background-color: #222222; - border-color: #080808; -} - -.navbar-inverse .navbar-brand { - color: #999999; -} - -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .navbar-nav > li > a { - color: #999999; -} - -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #ffffff; - background-color: #080808; -} - -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444444; - background-color: transparent; -} - -.navbar-inverse .navbar-toggle { - border-color: #333333; -} - -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333333; -} - -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #ffffff; -} - -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} - -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #ffffff; - background-color: #080808; -} - -.navbar-inverse .navbar-nav > .dropdown > a:hover .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .navbar-nav > .dropdown > a .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} - -.navbar-inverse .navbar-nav > .open > a .caret, -.navbar-inverse .navbar-nav > .open > a:hover .caret, -.navbar-inverse .navbar-nav > .open > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #999999; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #ffffff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #ffffff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444444; - background-color: transparent; - } -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover { - color: #ffffff; -} - -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; -} - -.breadcrumb > li + li:before { - padding: 0 5px; - color: #cccccc; - content: "/\00a0"; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} - -.pagination > li { - display: inline; -} - -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.428571429; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; -} - -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-bottom-left-radius: 4px; - border-top-left-radius: 4px; -} - -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} - -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - background-color: #eeeeee; -} - -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 2; - color: #ffffff; - cursor: default; - background-color: #428bca; - border-color: #428bca; -} - -.pagination > .disabled > span, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #999999; - cursor: not-allowed; - background-color: #ffffff; - border-color: #dddddd; -} - -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; -} - -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-bottom-left-radius: 6px; - border-top-left-radius: 6px; -} - -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} - -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; -} - -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} - -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} - -.pager:before, -.pager:after { - display: table; - content: " "; -} - -.pager:after { - clear: both; -} - -.pager:before, -.pager:after { - display: table; - content: " "; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.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: not-allowed; - background-color: #ffffff; -} - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #ffffff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} - -.label[href]:hover, -.label[href]:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label:empty { - display: none; -} - -.label-default { - background-color: #999999; -} - -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #808080; -} - -.label-primary { - background-color: #428bca; -} - -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #3071a9; -} - -.label-success { - background-color: #5cb85c; -} - -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} - -.label-info { - background-color: #5bc0de; -} - -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} - -.label-warning { - background-color: #f0ad4e; -} - -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} - -.label-danger { - background-color: #d9534f; -} - -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} - -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #ffffff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; - border-radius: 10px; -} - -.badge:empty { - display: none; -} - -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.btn .badge { - position: relative; - top: -1px; -} - -a.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #428bca; - background-color: #ffffff; -} - -.nav-pills > li > a > .badge { - margin-left: 3px; -} - -.jumbotron { - padding: 30px; - margin-bottom: 30px; - font-size: 21px; - font-weight: 200; - line-height: 2.1428571435; - color: inherit; - background-color: #eeeeee; -} - -.jumbotron h1 { - line-height: 1; - color: inherit; -} - -.jumbotron p { - line-height: 1.4; -} - -.container .jumbotron { - border-radius: 6px; -} - -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1 { - font-size: 63px; - } -} - -.thumbnail { - display: inline-block; - display: block; - height: auto; - max-width: 100%; - padding: 4px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.thumbnail > img { - display: block; - height: auto; - max-width: 100%; -} - -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #428bca; -} - -.thumbnail > img { - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; - color: #333333; -} - -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} - -.alert h4 { - margin-top: 0; - color: inherit; -} - -.alert .alert-link { - font-weight: bold; -} - -.alert > p, -.alert > ul { - margin-bottom: 0; -} - -.alert > p + p { - margin-top: 5px; -} - -.alert-dismissable { - padding-right: 35px; -} - -.alert-dismissable .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success hr { - border-top-color: #c9e2b3; -} - -.alert-success .alert-link { - color: #356635; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info hr { - border-top-color: #a6e1ec; -} - -.alert-info .alert-link { - color: #2d6987; -} - -.alert-warning { - color: #c09853; - background-color: #fcf8e3; - border-color: #fbeed5; -} - -.alert-warning hr { - border-top-color: #f8e5be; -} - -.alert-warning .alert-link { - color: #a47e3c; -} - -.alert-danger { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-danger hr { - border-top-color: #e6c1c7; -} - -.alert-danger .alert-link { - color: #953b39; -} - -@-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; - } -} - -@-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: #f5f5f5; - border-radius: 4px; - -webkit-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; - background-color: #428bca; - -webkit-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-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress-striped .progress-bar { - 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: 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-size: 40px 40px; -} - -.progress.active .progress-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-bar-success { - background-color: #5cb85c; -} - -.progress-striped .progress-bar-success { - 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: 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-bar-info { - background-color: #5bc0de; -} - -.progress-striped .progress-bar-info { - 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: 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-bar-warning { - background-color: #f0ad4e; -} - -.progress-striped .progress-bar-warning { - 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: 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-bar-danger { - background-color: #d9534f; -} - -.progress-striped .progress-bar-danger { - 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: 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); -} - -.media, -.media-body { - overflow: hidden; - 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 { - padding-left: 0; - list-style: none; -} - -.list-group { - padding-left: 0; - margin-bottom: 20px; -} - -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #ffffff; - border: 1px solid #dddddd; -} - -.list-group-item:first-child { - border-top-right-radius: 4px; - border-top-left-radius: 4px; -} - -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} - -.list-group-item > .badge { - float: right; -} - -.list-group-item > .badge + .badge { - margin-right: 5px; -} - -a.list-group-item { - color: #555555; -} - -a.list-group-item .list-group-item-heading { - color: #333333; -} - -a.list-group-item:hover, -a.list-group-item:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #ffffff; - background-color: #428bca; - border-color: #428bca; -} - -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading { - color: inherit; -} - -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #e1edf7; -} - -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} - -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} - -.panel { - margin-bottom: 20px; - background-color: #ffffff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.panel-body { - padding: 15px; -} - -.panel-body:before, -.panel-body:after { - display: table; - content: " "; -} - -.panel-body:after { - clear: both; -} - -.panel-body:before, -.panel-body:after { - display: table; - content: " "; -} - -.panel-body:after { - clear: both; -} - -.panel > .list-group { - margin-bottom: 0; -} - -.panel > .list-group .list-group-item { - border-width: 1px 0; -} - -.panel > .list-group .list-group-item:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.panel > .list-group .list-group-item:last-child { - border-bottom: 0; -} - -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} - -.panel > .table { - margin-bottom: 0; -} - -.panel > .panel-body + .table { - border-top: 1px solid #dddddd; -} - -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-right-radius: 3px; - border-top-left-radius: 3px; -} - -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; -} - -.panel-title > a { - color: inherit; -} - -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #dddddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} - -.panel-group .panel { - margin-bottom: 0; - overflow: hidden; - border-radius: 4px; -} - -.panel-group .panel + .panel { - margin-top: 5px; -} - -.panel-group .panel-heading { - border-bottom: 0; -} - -.panel-group .panel-heading + .panel-collapse .panel-body { - border-top: 1px solid #dddddd; -} - -.panel-group .panel-footer { - border-top: 0; -} - -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #dddddd; -} - -.panel-default { - border-color: #dddddd; -} - -.panel-default > .panel-heading { - color: #333333; - background-color: #f5f5f5; - border-color: #dddddd; -} - -.panel-default > .panel-heading + .panel-collapse .panel-body { - border-top-color: #dddddd; -} - -.panel-default > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #dddddd; -} - -.panel-primary { - border-color: #428bca; -} - -.panel-primary > .panel-heading { - color: #ffffff; - background-color: #428bca; - border-color: #428bca; -} - -.panel-primary > .panel-heading + .panel-collapse .panel-body { - border-top-color: #428bca; -} - -.panel-primary > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #428bca; -} - -.panel-success { - border-color: #d6e9c6; -} - -.panel-success > .panel-heading { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.panel-success > .panel-heading + .panel-collapse .panel-body { - border-top-color: #d6e9c6; -} - -.panel-success > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #d6e9c6; -} - -.panel-warning { - border-color: #fbeed5; -} - -.panel-warning > .panel-heading { - color: #c09853; - background-color: #fcf8e3; - border-color: #fbeed5; -} - -.panel-warning > .panel-heading + .panel-collapse .panel-body { - border-top-color: #fbeed5; -} - -.panel-warning > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #fbeed5; -} - -.panel-danger { - border-color: #eed3d7; -} - -.panel-danger > .panel-heading { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.panel-danger > .panel-heading + .panel-collapse .panel-body { - border-top-color: #eed3d7; -} - -.panel-danger > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #eed3d7; -} - -.panel-info { - border-color: #bce8f1; -} - -.panel-info > .panel-heading { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.panel-info > .panel-heading + .panel-collapse .panel-body { - border-top-color: #bce8f1; -} - -.panel-info > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #bce8f1; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-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-lg { - padding: 24px; - border-radius: 6px; -} - -.well-sm { - padding: 9px; - border-radius: 3px; -} - -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - 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.5; - filter: alpha(opacity=50); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.modal-open { - overflow: hidden; -} - -body.modal-open, -.modal-open .navbar-fixed-top, -.modal-open .navbar-fixed-bottom { - margin-right: 15px; -} - -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - display: none; - overflow: auto; - overflow-y: scroll; -} - -.modal.fade .modal-dialog { - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - transform: translate(0, -25%); - -webkit-transition: -webkit-transform 0.3s ease-out; - -moz-transition: -moz-transform 0.3s ease-out; - -o-transition: -o-transform 0.3s ease-out; - transition: transform 0.3s ease-out; -} - -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); -} - -.modal-dialog { - z-index: 1050; - width: auto; - padding: 10px; - margin-right: auto; - margin-left: auto; -} - -.modal-content { - position: relative; - background-color: #ffffff; - border: 1px solid #999999; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - background-clip: padding-box; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; - filter: alpha(opacity=0); -} - -.modal-backdrop.in { - opacity: 0.5; - filter: alpha(opacity=50); -} - -.modal-header { - min-height: 16.428571429px; - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} - -.modal-header .close { - margin-top: -2px; -} - -.modal-title { - margin: 0; - line-height: 1.428571429; -} - -.modal-body { - position: relative; - padding: 20px; -} - -.modal-footer { - padding: 19px 20px 20px; - margin-top: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -@media screen and (min-width: 768px) { - .modal-dialog { - right: auto; - left: 50%; - width: 600px; - padding-top: 30px; - padding-bottom: 30px; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - } -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 12px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.9; - filter: alpha(opacity=90); -} - -.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: 3px 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - 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.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.top-right .tooltip-arrow { - right: 5px; - bottom: 0; - 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; -} - -.tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 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 #cccccc; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - 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; - border-radius: 5px 5px 0 0; -} - -.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: #999999; - 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; - content: " "; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999999; - 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; - content: " "; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999999; - 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; - content: " "; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999999; - 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; - content: " "; -} - -.carousel { - position: relative; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-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; - height: auto; - max-width: 100%; - 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: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.left { - background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%)); - background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); -} - -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%)); - background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - left: 50%; - z-index: 5; - display: inline-block; -} - -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; -} - -.carousel-control .icon-prev:before { - content: '\2039'; -} - -.carousel-control .icon-next:before { - content: '\203a'; -} - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} - -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - border: 1px solid #ffffff; - border-radius: 10px; -} - -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #ffffff; -} - -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); -} - -.carousel-caption .btn { - text-shadow: none; -} - -@media screen and (min-width: 768px) { - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} - -.clearfix:before, -.clearfix:after { - display: table; - content: " "; -} - -.clearfix:after { - clear: both; -} - -.pull-right { - float: right !important; -} - -.pull-left { - float: left !important; -} - -.hide { - display: none !important; -} - -.show { - display: block !important; -} - -.invisible { - visibility: hidden; -} - -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.affix { - position: fixed; -} - -@-ms-viewport { - width: device-width; -} - -@media screen and (max-width: 400px) { - @-ms-viewport { - width: 320px; - } -} - -.hidden { - display: none !important; - visibility: hidden !important; -} - -.visible-xs { - display: none !important; -} - -tr.visible-xs { - display: none !important; -} - -th.visible-xs, -td.visible-xs { - display: none !important; -} - -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-xs.visible-sm { - display: block !important; - } - tr.visible-xs.visible-sm { - display: table-row !important; - } - th.visible-xs.visible-sm, - td.visible-xs.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-xs.visible-md { - display: block !important; - } - tr.visible-xs.visible-md { - display: table-row !important; - } - th.visible-xs.visible-md, - td.visible-xs.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-xs.visible-lg { - display: block !important; - } - tr.visible-xs.visible-lg { - display: table-row !important; - } - th.visible-xs.visible-lg, - td.visible-xs.visible-lg { - display: table-cell !important; - } -} - -.visible-sm { - display: none !important; -} - -tr.visible-sm { - display: none !important; -} - -th.visible-sm, -td.visible-sm { - display: none !important; -} - -@media (max-width: 767px) { - .visible-sm.visible-xs { - display: block !important; - } - tr.visible-sm.visible-xs { - display: table-row !important; - } - th.visible-sm.visible-xs, - td.visible-sm.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-sm.visible-md { - display: block !important; - } - tr.visible-sm.visible-md { - display: table-row !important; - } - th.visible-sm.visible-md, - td.visible-sm.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-sm.visible-lg { - display: block !important; - } - tr.visible-sm.visible-lg { - display: table-row !important; - } - th.visible-sm.visible-lg, - td.visible-sm.visible-lg { - display: table-cell !important; - } -} - -.visible-md { - display: none !important; -} - -tr.visible-md { - display: none !important; -} - -th.visible-md, -td.visible-md { - display: none !important; -} - -@media (max-width: 767px) { - .visible-md.visible-xs { - display: block !important; - } - tr.visible-md.visible-xs { - display: table-row !important; - } - th.visible-md.visible-xs, - td.visible-md.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-md.visible-sm { - display: block !important; - } - tr.visible-md.visible-sm { - display: table-row !important; - } - th.visible-md.visible-sm, - td.visible-md.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-md.visible-lg { - display: block !important; - } - tr.visible-md.visible-lg { - display: table-row !important; - } - th.visible-md.visible-lg, - td.visible-md.visible-lg { - display: table-cell !important; - } -} - -.visible-lg { - display: none !important; -} - -tr.visible-lg { - display: none !important; -} - -th.visible-lg, -td.visible-lg { - display: none !important; -} - -@media (max-width: 767px) { - .visible-lg.visible-xs { - display: block !important; - } - tr.visible-lg.visible-xs { - display: table-row !important; - } - th.visible-lg.visible-xs, - td.visible-lg.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-lg.visible-sm { - display: block !important; - } - tr.visible-lg.visible-sm { - display: table-row !important; - } - th.visible-lg.visible-sm, - td.visible-lg.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-lg.visible-md { - display: block !important; - } - tr.visible-lg.visible-md { - display: table-row !important; - } - th.visible-lg.visible-md, - td.visible-lg.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} - -.hidden-xs { - display: block !important; -} - -tr.hidden-xs { - display: table-row !important; -} - -th.hidden-xs, -td.hidden-xs { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } - tr.hidden-xs { - display: none !important; - } - th.hidden-xs, - td.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-xs.hidden-sm { - display: none !important; - } - tr.hidden-xs.hidden-sm { - display: none !important; - } - th.hidden-xs.hidden-sm, - td.hidden-xs.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-xs.hidden-md { - display: none !important; - } - tr.hidden-xs.hidden-md { - display: none !important; - } - th.hidden-xs.hidden-md, - td.hidden-xs.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-xs.hidden-lg { - display: none !important; - } - tr.hidden-xs.hidden-lg { - display: none !important; - } - th.hidden-xs.hidden-lg, - td.hidden-xs.hidden-lg { - display: none !important; - } -} - -.hidden-sm { - display: block !important; -} - -tr.hidden-sm { - display: table-row !important; -} - -th.hidden-sm, -td.hidden-sm { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-sm.hidden-xs { - display: none !important; - } - tr.hidden-sm.hidden-xs { - display: none !important; - } - th.hidden-sm.hidden-xs, - td.hidden-sm.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } - tr.hidden-sm { - display: none !important; - } - th.hidden-sm, - td.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-sm.hidden-md { - display: none !important; - } - tr.hidden-sm.hidden-md { - display: none !important; - } - th.hidden-sm.hidden-md, - td.hidden-sm.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-sm.hidden-lg { - display: none !important; - } - tr.hidden-sm.hidden-lg { - display: none !important; - } - th.hidden-sm.hidden-lg, - td.hidden-sm.hidden-lg { - display: none !important; - } -} - -.hidden-md { - display: block !important; -} - -tr.hidden-md { - display: table-row !important; -} - -th.hidden-md, -td.hidden-md { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-md.hidden-xs { - display: none !important; - } - tr.hidden-md.hidden-xs { - display: none !important; - } - th.hidden-md.hidden-xs, - td.hidden-md.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-md.hidden-sm { - display: none !important; - } - tr.hidden-md.hidden-sm { - display: none !important; - } - th.hidden-md.hidden-sm, - td.hidden-md.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } - tr.hidden-md { - display: none !important; - } - th.hidden-md, - td.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-md.hidden-lg { - display: none !important; - } - tr.hidden-md.hidden-lg { - display: none !important; - } - th.hidden-md.hidden-lg, - td.hidden-md.hidden-lg { - display: none !important; - } -} - -.hidden-lg { - display: block !important; -} - -tr.hidden-lg { - display: table-row !important; -} - -th.hidden-lg, -td.hidden-lg { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-lg.hidden-xs { - display: none !important; - } - tr.hidden-lg.hidden-xs { - display: none !important; - } - th.hidden-lg.hidden-xs, - td.hidden-lg.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-lg.hidden-sm { - display: none !important; - } - tr.hidden-lg.hidden-sm { - display: none !important; - } - th.hidden-lg.hidden-sm, - td.hidden-lg.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-lg.hidden-md { - display: none !important; - } - tr.hidden-lg.hidden-md { - display: none !important; - } - th.hidden-lg.hidden-md, - td.hidden-lg.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } - tr.hidden-lg { - display: none !important; - } - th.hidden-lg, - td.hidden-lg { - display: none !important; - } -} - -.visible-print { - display: none !important; -} - -tr.visible-print { - display: none !important; -} - -th.visible-print, -td.visible-print { - display: none !important; -} - -@media print { - .visible-print { - display: block !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } - .hidden-print { - display: none !important; - } - tr.hidden-print { - display: none !important; - } - th.hidden-print, - td.hidden-print { - display: none !important; - } -} \ No newline at end of file diff --git a/www/css/bootstrap.min.css b/www/css/bootstrap.min.css deleted file mode 100644 index a553c4f..0000000 --- a/www/css/bootstrap.min.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap v3.0.0 - * - * Copyright 2013 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. - *//*! normalize.css v2.1.0 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}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-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@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:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select[multiple],textarea{background-image:none}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16.099999999999998px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-warning{color:#c09853}.text-danger{color:#b94a48}.text-success{color:#468847}.text-info{color:#3a87ad}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h4,h5,h6{margin-top:10px;margin-bottom:10px}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}h1 small,.h1 small{font-size:24px}h2 small,.h2 small{font-size:18px}h3 small,.h3 small,h4 small,.h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.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}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;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:1.428571429}code,pre{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-1{width:8.333333333333332%}.col-xs-2{width:16.666666666666664%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333333333%}.col-xs-5{width:41.66666666666667%}.col-xs-6{width:50%}.col-xs-7{width:58.333333333333336%}.col-xs-8{width:66.66666666666666%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333333334%}.col-xs-11{width:91.66666666666666%}.col-xs-12{width:100%}@media(min-width:768px){.container{max-width:750px}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left}.col-sm-1{width:8.333333333333332%}.col-sm-2{width:16.666666666666664%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333333333%}.col-sm-5{width:41.66666666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.333333333333336%}.col-sm-8{width:66.66666666666666%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333333334%}.col-sm-11{width:91.66666666666666%}.col-sm-12{width:100%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-11{left:91.66666666666666%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-11{margin-left:91.66666666666666%}}@media(min-width:992px){.container{max-width:970px}.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left}.col-md-1{width:8.333333333333332%}.col-md-2{width:16.666666666666664%}.col-md-3{width:25%}.col-md-4{width:33.33333333333333%}.col-md-5{width:41.66666666666667%}.col-md-6{width:50%}.col-md-7{width:58.333333333333336%}.col-md-8{width:66.66666666666666%}.col-md-9{width:75%}.col-md-10{width:83.33333333333334%}.col-md-11{width:91.66666666666666%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.333333333333332%}.col-md-push-2{left:16.666666666666664%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333333333%}.col-md-push-5{left:41.66666666666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.333333333333336%}.col-md-push-8{left:66.66666666666666%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333333334%}.col-md-push-11{left:91.66666666666666%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-11{right:91.66666666666666%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-11{margin-left:91.66666666666666%}}@media(min-width:1200px){.container{max-width:1170px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left}.col-lg-1{width:8.333333333333332%}.col-lg-2{width:16.666666666666664%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333333333%}.col-lg-5{width:41.66666666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.333333333333336%}.col-lg-8{width:66.66666666666666%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333333334%}.col-lg-11{width:91.66666666666666%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-11{left:91.66666666666666%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-11{margin-left:91.66666666666666%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table thead>tr>th,.table tbody>tr>th,.table tfoot>tr>th,.table thead>tr>td,.table tbody>tr>td,.table tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table caption+thead tr:first-child th,.table colgroup+thead tr:first-child th,.table thead:first-child tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed thead>tr>th,.table-condensed tbody>tr>th,.table-condensed tfoot>tr>th,.table-condensed thead>tr>td,.table-condensed tbody>tr>td,.table-condensed tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.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 col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8;border-color:#d6e9c6}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td{background-color:#d0e9c6;border-color:#c9e2b3}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede;border-color:#eed3d7}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td{background-color:#ebcccc;border-color:#e6c1c7}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3;border-color:#fbeed5}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td{background-color:#faf2cc;border-color:#f8e5be}@media(max-width:768px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0;background-color:#fff}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>thead>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>thead>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}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}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-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-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-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}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-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}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-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}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{padding-top:7px;margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-print:before{content:"\e045"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-briefcase:before{content:"\1f4bc"}.glyphicon-calendar:before{content:"\1f4c5"}.glyphicon-pushpin:before{content:"\1f4cc"}.glyphicon-paperclip:before{content:"\1f4ce"}.glyphicon-camera:before{content:"\1f4f7"}.glyphicon-lock:before{content:"\1f512"}.glyphicon-bell:before{content:"\1f514"}.glyphicon-bookmark:before{content:"\1f516"}.glyphicon-fire:before{content:"\1f525"}.glyphicon-wrench:before{content:"\1f527"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent;content:""}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.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;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#fff;text-decoration:none;background-color:#428bca}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}}.nav-tabs.nav-justified>li>a{margin-right:0;border-bottom:1px solid #ddd}.nav-tabs.nav-justified>.active>a{border-bottom-color:#fff}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:5px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-bottom:1px solid #ddd}.nav-tabs-justified>.active>a{border-bottom-color:#fff}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;z-index:1000;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;border-width:0 0 1px}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;z-index:1030}.navbar-fixed-bottom{bottom:0;margin-bottom:0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-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)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e6e6e6}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;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;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.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:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%}a.thumbnail:hover,a.thumbnail:focus{border-color:#428bca}.thumbnail>img{margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-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}}@-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:#f5f5f5;border-radius:4px;-webkit-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:#fff;text-align:center;background-color:#428bca;-webkit-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-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{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: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-size:40px 40px}.progress.active .progress-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-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{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: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-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{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: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-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{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: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-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{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: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)}.media,.media-body{overflow:hidden;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{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table{margin-bottom:0}.panel>.panel-body+.table{border-top:1px solid #ddd}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#fbeed5}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#eed3d7}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#eed3d7}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-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-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}body.modal-open,.modal-open .navbar-fixed-top,.modal-open .navbar-fixed-bottom{margin-right:15px}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{right:auto;left:50%;width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.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:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;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:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;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:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);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;border-radius:5px 5px 0 0}.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:#fff;border-bottom-width:0;content:" "}.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:#fff;border-left-width:0;content:" "}.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:#fff;border-top-width:0;content:" "}.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:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;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:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;left:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media screen and (max-width:400px){@-ms-viewport{width:320px}}.hidden{display:none!important;visibility:hidden!important}.visible-xs{display:none!important}tr.visible-xs{display:none!important}th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm{display:none!important}tr.visible-sm{display:none!important}th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md{display:none!important}tr.visible-md{display:none!important}th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg{display:none!important}tr.visible-lg{display:none!important}th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs{display:none!important}tr.hidden-xs{display:none!important}th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm{display:none!important}tr.hidden-xs.hidden-sm{display:none!important}th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md{display:none!important}tr.hidden-xs.hidden-md{display:none!important}th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg{display:none!important}tr.hidden-xs.hidden-lg{display:none!important}th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs{display:none!important}tr.hidden-sm.hidden-xs{display:none!important}th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}tr.hidden-sm{display:none!important}th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md{display:none!important}tr.hidden-sm.hidden-md{display:none!important}th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg{display:none!important}tr.hidden-sm.hidden-lg{display:none!important}th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs{display:none!important}tr.hidden-md.hidden-xs{display:none!important}th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm{display:none!important}tr.hidden-md.hidden-sm{display:none!important}th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}tr.hidden-md{display:none!important}th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg{display:none!important}tr.hidden-md.hidden-lg{display:none!important}th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs{display:none!important}tr.hidden-lg.hidden-xs{display:none!important}th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm{display:none!important}tr.hidden-lg.hidden-sm{display:none!important}th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md{display:none!important}tr.hidden-lg.hidden-md{display:none!important}th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg{display:none!important}tr.hidden-lg{display:none!important}th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print{display:none!important}tr.visible-print{display:none!important}th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print{display:none!important}tr.hidden-print{display:none!important}th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/www/css/search.css b/www/css/search.css deleted file mode 100644 index de9376d..0000000 --- a/www/css/search.css +++ /dev/null @@ -1,73 +0,0 @@ -.custom-combobox { - position: relative; - display: inline-block; -} - -.custom-combobox-toggle { - position: absolute; - top: 0; - bottom: 0; - margin-left: -1px; - padding: 0; - /* support: IE7 */ - *height: 1.7em; - *top: 0.1em; -} - -.custom-combobox-input { - margin: 0; - padding: 0.3em; -} - -.combobox-container .add-on{ - height:34px !important; - width:30px; -} - -.combobox-selected{ - -} - -.combobox-selected .caret{ - display:inline-block; -} - -.customDropdown { - /*display: block; - width: 100%;*/ - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.428571429; - color: #555; - vertical-align: middle; - background-color: #fff; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-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-color ease-in-out .15s,box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; -} - -#btnSearch{ - margin-left:5px; -} - -.searchLI{ - padding-top: 10px !important; - padding-bottom: 5px !important; -} - -#searchContainer { - margin-top: -1px; -} - -#searchContainer .combobox-container:before, #searchContainer .combobox-container:after { - display: none; - -} - -.search { - min-width:310px; width: auto !important; width: 310px; -} diff --git a/www/exodus.html b/www/exodus.html deleted file mode 100644 index 5e18927..0000000 --- a/www/exodus.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - Exodus Transaction - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- - - - - -
Transaction{{transactionInformation.tx_hash}}
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - -
Basic Information
From{{transactionInformation.from_address}}
To{{transactionInformation.to_address}}
Currency{{transactionInformation.currency_str}}
Amount{{transactionInformation.formatted_amount}}
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Information
Transaction type - - {{transactionInformation.tx_type_str}} -
Included in block{{transactionInformation.block}}
Index in block{{transactionInformation.index}}
Block time{{transactionInformation.tx_time | date:'yyyy-MM-dd HH:mm:ss UTC'}}
Transaction method{{transactionInformation.method}}
Valid -
- Invalid -
-
- Valid -
-
-
-
-
-
- -
-
- -
-
-
- - - - diff --git a/www/fonts/glyphicons-halflings-regular.eot b/www/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index 87eaa434234e2a984c261e0450a2f4ad837aa7b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14079 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 diff --git a/www/fonts/glyphicons-halflings-regular.svg b/www/fonts/glyphicons-halflings-regular.svg deleted file mode 100644 index 5fee068..0000000 --- a/www/fonts/glyphicons-halflings-regular.svg +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/www/fonts/glyphicons-halflings-regular.ttf b/www/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index be784dc1d5bcb92ab155f578f3723524a3dd9688..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29512 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 DlhOCh diff --git a/www/fonts/glyphicons-halflings-regular.woff b/www/fonts/glyphicons-halflings-regular.woff deleted file mode 100644 index 2cc3e4852a5a42e6aadd6284e067b66e14a57bc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16448 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 diff --git a/www/ico/apple-touch-icon-144-precomposed.png b/www/ico/apple-touch-icon-144-precomposed.png deleted file mode 100644 index 22ef08a4361304e7beebb84119604ba9b7e14c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3614 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 ayZaXD1QVZFQZ4Y`CtzV_gZtZ*81aAXtFqGo diff --git a/www/ico/apple-touch-icon-57-precomposed.png b/www/ico/apple-touch-icon-57-precomposed.png deleted file mode 100644 index 8e139fdf05aa80bd107a5ff216e27d8e887c536b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1577 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 SH0t&M0000ijMHK$-W1oF)X}c|b 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 N002ovPDHLkV1gV3Oz!{y diff --git a/www/ico/bitcoin48b.png b/www/ico/bitcoin48b.png deleted file mode 100644 index ab2825ddec5355341ad22c1e273221d986baa097..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5446 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 diff --git a/www/ico/coins24b.png b/www/ico/coins24b.png deleted file mode 100644 index 47d7515f193ecc605982811bcfb6e9df8f199e8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4153 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 DP@m^g diff --git a/www/ico/coins24t.png b/www/ico/coins24t.png deleted file mode 100644 index 2d7353c0089490b7b635f501b9135e518afba6ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3312 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 mx=uK&06oAV;5FdN{{{dSyXMmVynJN<0000p diff --git a/www/ico/coins32t.png b/www/ico/coins32t.png deleted file mode 100644 index 6f0a4577b051573b69febe100bc3c8208c2ef9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3601 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 Vov1Xo;#mLy002ovPDHLkV1lP>>7f7s diff --git a/www/ico/coins48t.png b/www/ico/coins48t.png deleted file mode 100644 index 49ca445013abd4e12be1178a41719746b982329a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4035 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 diff --git a/www/ico/exodus.png b/www/ico/exodus.png deleted file mode 100644 index 39285f3e00c88644e424ca074c0da1f17f8aef48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1313 zcmV++1>X9JP)IzAA7iRg2yh(a2K|VL2M-Wp z2Kq)PF*!Srnn#ORx23uiBNH>&T2l_6s<7^_-dkYE4GS{Wv=?A}4cFlCohZhq6HpbI z@5iR%NTxI#?-;L;UJ!Ttk{CWmXm+qfTpG4SA8z4WG59c3sxXW6Ejj2v6f0h zPp6p`Dq%c+FGfyAc~5a(7>%3Cc};A@pFJZ8I?+22!2^+3cGj;)evY5gRS=tB#)GV3Av7Ck4Tx7waqe5;7HEKCvin47Vuq3RKalI>(b zsIgB4QkcENy}5^ zp|L5Py)?`$lIcj$uh3xwg^?h3ZQjUxlEfG>CUU5Msw#@mP+f+9dPfloWU(l_(4wFQ zMQx;Yno((_2%2Ovg)KD|s90xV-*a;uzhAiF$)c9`uGloJJ}_57B;>UnPve;lrBJDf z2r+aJ1%GPm!Je%(?w*T%|KiHvI9}gb&-cxZ)hNjiV~%E#Vvl~ilPw3b2iE$HWqdgj zPb{LnI|n;9SGl^Lf!nw?G=cd167nJ;6cJ<~%C=(lWIMYg(Gutn3YfA1x9 zvqaVB>nf=x0cbSV@6hPDd2150v3Yb}9pzCk^t+pC!NK#4Ga%Kz@%cQZ5*FS{3nSF# ziZymU?*hS!7-b;S$u%@Cgj&#bk{V0w&7;ES=Z07>YBzB&>WuUy)zo!G&{7z>JsI`X zBlFGXV0xd7I!=AmbP^5yC}lT2o8W!o-lr&hj%>+lek3?E6I&=(Xa@L%5lOaVYx?%Rw{{)=Uw{Ds XVIVA0sx{bP00000NkvXXu0mjfkxgTt diff --git a/www/ico/exodus24b.png b/www/ico/exodus24b.png deleted file mode 100644 index d7f71167ca2d5156401811f82b127ed2fc067b26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4036 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 diff --git a/www/ico/exodus24t_.png b/www/ico/exodus24t_.png deleted file mode 100644 index 932ae334169d42deef3238034b693edb33ae649d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3247 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 LNkvXXu0mjfb5k#& diff --git a/www/ico/exodus48b.png b/www/ico/exodus48b.png deleted file mode 100644 index 38078c7fe94429a8f00d0a6bf2c9aa1f9a416f2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5114 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 diff --git a/www/ico/favicon.png b/www/ico/favicon.png deleted file mode 100644 index 56aa877f2a28a111d1992b187348a810cc05dcb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 889 zcmV-<1BU#GP)fC>sDXo4A{B*th&LJUO3#EC{@(2FKI ziHR3Icw$o#H5@o-Jg|8zyJ~oEdYU%AdB#e9=YLmsGi}PUJDr@Lo8!Qk4k*o%or4ll zCh`z>re}`xa}I2Zaj*HHIz~ZFMmrRTXhU8t?)c~Jq!r1)T<`CjAsR zIQF;gT;{ivVw#hXkJ3;xFeBR;nGa)M;EC@gbT;>5NI)??xCf=8CdlKMk?q2r7th`( zVwy(COKF5$(g4iJRhpTbSA5H2xycQ%o17rKlInpO`6%K{f181x3xjYOoks(3_tr2> zf1Lqw-oG1_W4fHAnY_`)>n3eI1{5&dXQq|80(G{K7+UpLIXJ{{(Sv_dot)a0`m5A)8~Wf#nJ@q}nc=!NXkd8KPJqSQ8Q?(bbS0 zeTXn4AH~ePe)U$4k*rMzmmGjhjwwHi^mgKm^D9?vcdh3REb!+Mr_0kT#JG)UKV+Z{ zs0vtUQ2B1s0VWk!$??!&-$VHpgkTl1lS;6y4`8aGyq$ai)m7qlUF|nOoUxHl6thzd zRe)_>1z5>G!c;#~-cFqHkx7andAotW2g?p%6Jiz=wO5xORSwL^N0ASpU!}0!)k}l? z4=jQ>zI#tYgOTMVEwW6<@a=@4ayv7Fhsn>b3k|MCrI4ywQvytiDYr8dZ>qg0#z+be z2Du@5wHufe<0^>wc1CAxv&oQb-sN&Hk6|FouK}i3o^~C_rF!Zy#(Rlodm3VqYmz+nW=iIz7;5X~ro_lTC^2u7E@ zy0Hd-e~F};AexoI*9v;_>dcbIE3{*=;1p(K3!axqLK(7>gJ?LeqOAl@G#0z?4o3wK zYN&3;?^utAXc7G1mtY;n3p)A%)U)VE^a|dH2ID_8;RnH6szWpek457|lNzLG!#&Y9 zMV^{)`4f0wg4^7!f{N&zc_=XwZK2GpjypgtiX0G&1B6un|o4SYmA^EX;xHO nFOCU5H1b*F1Yc?2|E2#CcXr(T0isM600000NkvXXu0mjft_wWv diff --git a/www/ico/sellaccept24b.png b/www/ico/sellaccept24b.png deleted file mode 100644 index 24afd09ac49f01d1f353d0d090603f759ef606a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4328 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 bwETAfYsE_+x~AZ+00000NkvXXu0mjfKCWbG diff --git a/www/ico/sellaccept32t.png b/www/ico/sellaccept32t.png deleted file mode 100644 index 81b78b5ab1fb3195d4d1d1334c58a5e8c9bde61c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3529 zcmV;)4L0(LP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0008?NklcHs0fi&Wyra_4kK?ki4tR@&me8m?rML#F&!sc*ua&9tkP&aHi zd!K)=_3wSw`qw@sm3P@{c*pHMf!ZqZ3xL(Y7~m3c66gWO1FL|~fH%N#pt*>_QWZg1 z4}1l*1NVSM;rvfvC9tppzHvaSYLVWk-cgq%bIa6w=C|Dg*)HPzfcmdGKgJ)ZyVUy@ zYdeQRpi#Z8&Q6@4?8ngy^}PB#Gyf(CS508A+L`PebzMKs@2Z;u^Qn5V0_MA-1WM|D zwM(6wdG|#H!@sH1GPqiGgL*B4ZBR$#5h$tk6?R_kAF9o2pL!z*<(=Y0b&vWi2>hpR z%pz6K5fw}7pQ^OigzTCM)0ZizTh{l4HakBKxzouyu>5U>qu zO5PDO}&uVX^tQsFb%&<7QI%VCgZvs0^`(EYEz^k z>PI2rXVkHk)>SIU@mYzJn<_gxFj1P%iw;3jY$Xak-Uy$}2X{1l6N zf#EU#2zUt0O0d1*{C8kdWX75x+5&6?76ToFsfM4ZFO%bcr1q*kAttH%9gOciDG{u4 z&G=@p#b~N}IgIp0Je1oX@x2!&_#f22LjB5FaaP?ilxjF7qCbu19(8NfiyP{K1ixQx zRVT!Fy?Q#EdezVr7u4s}j~|25_|Mf5if^+JNWB6ijm1*P2TL$v-@ zKMw5DAlR-RsZc2gMW9?MXT;7`pCskFH7Z_%+M*r{{D5|=xt0rb0(HO%;03S(SQiE8 zXJ8(1C$zuVZMTXO$o7@7^XuxjgSAt7|8MxeC-8OvXP7#57^M&U00000NkvXXu0mjf Ds*#v1 diff --git a/www/ico/sellaccept48.png b/www/ico/sellaccept48.png deleted file mode 100644 index 3ed8f9feadfa1b1992f3a2b5c14b94892eec0819..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3741 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 Hu0mjfIu==1 diff --git a/www/ico/sellaccept48b.png b/www/ico/sellaccept48b.png deleted file mode 100644 index e9d791ff65b202e3e604b3ae0c9409da1b5108a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6485 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 diff --git a/www/ico/sellaccept48t.png b/www/ico/sellaccept48t.png deleted file mode 100644 index 29cd76139f89f7b4a3b527864dd01e306419d2b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3913 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 X*ZqAnQT`$(00000NkvXXu0mjfGsa(0 diff --git a/www/ico/selloffer.png b/www/ico/selloffer.png deleted file mode 100644 index ea202c927b28f7d826b99f052a138ed0a7e07426..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1725 zcmV;u215CXP)8RQrug+bpxMnO~yYIxcH|!P_@-V#{+}oHz z#(k2AaUH3ujO#6TOTrPRDj`qRr@>GpTTUAGwITQQJrzt#?(Lvn zYv$`=dpoF1jSSFOf-G&AC5V1VzyCC;T9SH>GA8Pk6Ou{@l@cswQJyi~P+5}19^)`# zx+97tnZ|KBeWJt9$od(x8gxR5EB6N@#8zo=XIceewA|?twVOh<%P3tIA}iU@!S}iH z6j_GFk}CH7!LXit`r6Y}L2NNB@M8hm4@aY>(}V#QV*qjZ$?0RUW>Gl`Tn+?65uEt_ zCf@q&N8IW1A=8$IPgXC4+i4TfS-lezlzOn#i z#cpx0C_2-;x$`K#J<|YdT8cqThP9DM1bI#?-mZR3C_me93&C&{PfRYx^Rvs)-5WrD zmJJh0U@jSuNB5KHJ`|3CQ@D#FmX~cKWt1SM%jEC)H-il4=@RLb_#QL9rU48QQdXE_ zhr^l*Um%Q{4-RAh&sT)iWAmJdMxq!q!YQ7AyM9}&p28d`i03~Xi6Z6@HzLAAP1o*k zent7p?U?=AP8`4R2N|sDzhki~Fqo;m+eg6BV6~)R%S&^xyY@WJUb%@*uV3)@_=0R9 z@baInC@pkh+^B3Jj4{njqh89)0IvQ@CE=D7MXWw@R7wE6tQl=Gg}C{~t-IKM=$zPF z_{cbHS~`oGMmtVk`ilg}@D${Ty{pY_==KFr0|P+q5)U02LV8Ah#gAw{_k)Kor9i0{Snt%uOo*^8Wv zbi7zK1x^A|evU(ke0pXXoc44foTniYiAR7De=zb;OQ^0rwRM>J@^(~j+zTHWBN=l8 zPnB5(fj|gTOY*UK#awJ#H6K6JHRAB81|fiZUNSO^I6xJLt1Bl9WB64{(TRmyq6nrE z($fepf{@HC=sI}rbq>+YR4MK$^Vic03kQ;o!1v7KWk^d=F_FSQV`33#Y{JoV*Myik zQ^%r_FtKvWL1B!iC|7VtLsKi}SCk6yR#kZLLe(_TjDgW3vr*u7VnXoxYrjHxz5S3AveoT_)yVJa`=1Bh9f9qE~nk78fIceDy#XZlOmHTc;2AW z!rTmuB;{P-_2zae&8T2MRZ)maLxPmJAO}T<=aTb=jR2{|V~$=@%<0?k)O_!y>hV*$ z^^Tx|yXT0t| z)%Kro?qg!^KLPchk_NQnWUF?Md2cww$6zuN+VO+;HrdKSC`;1+hGukiHWw2q$;A0>LC%9ne0p1E+fW!kl-))HP;v3YN({{z~8`nNpr&uI@Sf5=mKX7jq|R!Ce} zXOG|Z;ok2z96MdVxU;)AH(t+ubEw@nD9xP1VN36rS?>92?eYa1^IVzj{|YbwK@%go T;t9B%00000NkvXXu0mjfdp$_m diff --git a/www/ico/selloffer24b.png b/www/ico/selloffer24b.png deleted file mode 100644 index 2876705302dbe931391234d9c71c1e4c66091ae2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 928 zcmV;R17G}!P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ7>wf?9d3F-^G3N^4`2R zlYs|!?mg!}|M|~7=WcuIy$b+u18)F3kN|-ozE*tSZ6w!(_Rg-3bXKO1Jm3guz8$c& zRwuv?;Bx-`NFRc79mH^;EOP8H4wTJYDJfH=`aGFgS8X%0*s>m* zw&o#A6*N;8fv^ssaUX#Z)=zktb&;w%JBRKA)zvz+`Z|~q3>UeySdGpiPyn;d4;UQC6I4q05-YcM-GieDa}_~^p`)YjGs{34C! z25-%O&B14$VCK1f1b!(3d~C&z7LLs5w)qEa%^b2bt*&zgcQZs%)b5xzM}jQ1 zR`jXuT<1N+$4DO1A*C`Qnlo7$s`Jyj4lDr2{vQC#V>BgC%q3X>0000pw diff --git a/www/ico/selloffer24b_.png b/www/ico/selloffer24b_.png deleted file mode 100644 index b32b1573766f94b4d4458b3fa2119f818b60e899..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3965 zcmV-@4}$QCP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000E2Nkl9(E6vuz}zBg~$=?Ap7&{iw0AQZ47A4a38gb;`tL*hbWBq}b5 zi7}`#A+m7cMoipDs$wJbCg@O1%Qh`cB!Z#Q!D1};>>CC)$&vEhYOox`m zOa3|c+;h*zz5o9+{af~i!0W&!paXEI0tyPXSZnR60q{PPI6(Cps=L&=9hKmNsG8J4 z(#>MPNE%cPAU=pmeMG@jaB4=mu6Sxo)SITRQNc|iP7^i0d^O%#YVh=+Xl-EM8lzLHG@vS>s+(+unbHdJ z0Z9*2-;(Nqm6_Grs$V+4@Q%!!QceU^$OJZ>p(;t@P!$4eu*TpLhp3RT0fuy4YJvxW z#rOklb@EOq6w5>bWCKfnqKtC_PCy(+6-^vQ97Z8f1$C%jvw%T;V8MuhIzq&usubgd zmsa-i@~VdjjA8GQQ+##k1T!15e7JEnZOu7$9{7X(zn$j&4FmLbxAD#w-*bH|&s)zw z#>yqVL}7pp3?F^_Glx%Hps_B4HL4WLF@2pae6V4F+l3Ow7`Co|f_WV?X>G`|X4wNQ zo!7yWi@QnUgvE2(8R);Cz(7(?=G(0$F6(8YSYp|{E^drZFkUFJpu3e^6i|#43Z)pF!yqJ1D3%l6`|==1PhO^_sh(Um zgNR_&3H2Gv@VTq}Fm#^vPc35oz(Tg|Il}O{t30}(i?Mu>p)*(L?P#U7u`ZoW^|2|5 zb7V6igKw{6-?mqok&B4SX#y5i0t7VwqyGL})F=a?F;&{roa~fu7D5GC_cfe+QB{ ztcA5J=F-+&kEn91P^P6JOLzMW{yaazi8CW?e0BvZ`tBtP19Ei{ySBc-(5b)3W&(2A zh>tg~V{|OfcL$Gh_}Dob>LP-+N1k~%6WFGUBR43P6P7>NMXoNxj(xv!{Pf=}>Yc^z zgG1~&bd1G49b6q9=lWQlY!uMaoTE@IbK%M;)*2eJ5%nhN!1}@tVMN9jFzURJwdZrmA8XtzqR!9I9$qIc+-cPinHJ z{O%={8eGYkJFpioYjH9Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8k3C%+Ln>~)2@T|J zHW0Cy#_8as8p0$r!GPV_N!5V;0RyMU3KkUu*6s6Oe+%O{x#`1o?^)ksIf-wnArMSo@+ie*o_cq7NNYHjtT?r-&3 zf}2z($V@Sr$aCkAEJw>9yWeb%*XBHOEt~(UmixiHt(qBfKHP_|&kKC*xo(xps!LB; s)Z}`aThfkedMwiV?+5|@qpm!NOUHx3vIVCg!0LJWs^8f$< diff --git a/www/ico/selloffer24t_.png b/www/ico/selloffer24t_.png deleted file mode 100644 index a7b3d2aa5bfb88247daf4f9cd95b1bd10c99cd70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3183 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 WR2grj1-WSe0000VaMb-QV?p=)wTi)66 z)$v-{Ia!|^vyXwvi&t;`6ZHDHE%W4c@(11&HUF%;@UDpU^!ZaMS9wyLr zzb3!Smf>C-?0NE9@#AGiyH}o7x+Jo!;?n=cfsI=~HgWCB)_T!fxB1)wxr)MA-&y|R uyJAh=mF~Z_yW2dGfrA0)jX%{4_n8@j`$Pn#o5Ig90D-5gpUXO@geCyc%b&pj diff --git a/www/ico/selloffer48b.png b/www/ico/selloffer48b.png deleted file mode 100644 index f7d5d7cd3c116c168aa73dde8c9403f467e14f0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5217 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 blm8n4bKuRT@|UJ100000NkvXXu0mjfWjW$w diff --git a/www/ico/selloffer48t.png b/www/ico/selloffer48t.png deleted file mode 100644 index 9a535e31cc0c69e165ed0edebb08cd151bab49f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3532 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 b9p3{0U4gg~IAuTQ00000NkvXXu0mjfppvHK diff --git a/www/ico/simplesend24b.png b/www/ico/simplesend24b.png deleted file mode 100644 index 2216c4202ff9803a67871326ba81747f3feeaf1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 990 zcmV<410np0P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ;sB&IDTulg8ck!X!t1ZgF7Ar-2)X>cL5;Db^S z?ZS4WMi5<0=IpbFxN>Zia;4f~BPr2O0eYkyT6H?@ipmTAS}C(qu5#7*R?a?mnEkt_`M120 z+T=1J1B;2K_RcSWMv&z?A)nKB(H&xCt-=TAmzkR_QJUDs{Jvd8-t+a+uM|AA%97Tz z98K;yxPUZ*z%ukoezQp0VM|b{)_ME0C9b_tQ_OJ(PXJcP(GQV4wf-7;&H8vAa(hFw=ra_8O|zWU)8 z*4Ar84kVQWW^B|NoIJ9h`MK+p5HI1=XvAr1;ijECIJbC|+mF3Yt=>q$Aj2bePHm%D zh%kxG-q9+P_dYwjtT==$PK)dam{AO#W2ZjFyH;)b6JA~}SE_`_@yyY?ICS6^0Dk}T z0w-SikXo&g)Imm&SrTfj0h633zC>QDRGBGF@aB{EGE1{h?PA(Af_^O7oBu-OsBF|(EpPDd7fZZw`g4YdA_|d9 zroL-10o;xEE&cBwg3PC M07*qoM6N<$f*4ZN3IG5A diff --git a/www/ico/simplesend24b_.png b/www/ico/simplesend24b_.png deleted file mode 100644 index 8015286c47f2781677b8be22157919c88500180f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3813 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 b9p3{0U4gg~IAuTQ00000NkvXXu0mjfppvHK diff --git a/www/ico/simplesend32b.png b/www/ico/simplesend32b.png deleted file mode 100644 index 3d6d361fa5685cb5c5049c5fbb6ff85ec2cfafbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4011 zcmV;c4^;4pP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000EmNkl}JgYgmq3JGXPq(KBR0V+2GE!a>BZFl$k&hg>SXzv1Hf4q%f*<@s_DYZW1==uAFD zWeybIyWF8Vt<#1{y%59xCM~$K~VIAs1m~JPwN)QNsAS9i| zV8(GGuEU`+;nR*rEC`fTjiaS0#o5dKSYt>!i;9k;BcwKrp+t*CRN_=s!o-SD6A`jm zpSM;&!ng0NV#CU%hy;v`WHCky`7vr}G;+K}Ms1KHI?AZ3MDr09!6+a?I^&b@EbE?r zm=9lliaY9)3=9rqR6qpHjfiIy^`sYF0z}nbLog@?ICSCyH3^S}vs#(eHie~g z+xYX`RnGNZr^Z<@CZ>B-Xa>A#i=PV}D2i=K9+c!o1fhYz57>9~EY}8x>6m{vZOu(A zUvwYmd$03*&lQrM#WV2(Mmj?W6m1xr@@^S{6OK0i^+>NT3X-Gi0+q*=#`856Jp{$ooNzW{P+}2yhlo{@u&| z?jB~(n94n^lj)d$H!YJ={Bq(vw}vxeNHibj0heb)aK`Z9%w{}mORHU>ghg2#&xZ(C zjKbh>nh(DImHN6Qi{`ZPV&?+xoj!$)JAdF}-*sveUj7<7Buu2ip)_lsT)>t!9aw8( z_9yzYh6o|a&$T}=laDv9WYy-+7*1#LqQrE$#PERL{y|Rv^DoX?O6@CPiV!LN89+oC zN@tkaI++HN`L!E2N02~bh&rNso~m{1@9yF7ALsF`MT;{w_uo{$6$Ti|_@vWWx*na! zmY1K%8~<|OG2Z)pKSRSAlFpK=z^+iGAYm;dnJlVdEXQt8N^ivAP=?0(B%5AZ#@enW zIM348f0M1d_VUev<0KP~+Jq}S)2cYtxUz&bpt%Rd#1kz>bH&Bt2LXdaX_nl77jM7P z$-+4^065TnhV8rdakA$!O{to&9*M*bQb3@p7c9;z5ClHHAFyskJL}gxMq{dmp>&py zb{}Hrp2K7^K9lNe3niX-@8Kx&s4UGJjK@6i70-ihuXXXlvWEcp>s%l2e)1y+yU$Qx zm!zRCiAqqhHFKq>FO9oW>I|v`K|o_&ElcLj1Yq}1$JqYqUi$h6nN(i`YC_0MI<1%k zQf(7iLX*yLXKX*@4QT;)YbUd{QP{u11_ViLS?h6J`ObIk6zV{CKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z00044NklBK`>7DzM*eG!t_5ve7H_*;8c>@dsJHTX!9RQ0!Gd?g0unjB#FKq%u zzzR>Hjo zumW8DMjwcKSzS{f!X~^_=kuz9iP-K}Jygf@D#Mz39Tsk>>p_iQZ$!OnJ@(Wm>hyQ> zvjC{7XJPR@wUQ=3%ILFvDU{qQaF?oVivNNFpaA&y0B-{T-ro#JvRx&700000NkvXX Hu0mjf%pAr# diff --git a/www/ico/simplesend48b.png b/www/ico/simplesend48b.png deleted file mode 100644 index 28f9be55880037c73534ba2feb7b4620f982e8f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4759 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 diff --git a/www/ico/simplesend48t.png b/www/ico/simplesend48t.png deleted file mode 100644 index 33ee20db7f0e78bd34f6be8a32dca9d8489a5e83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3230 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 diff --git a/www/ico/undefined24t.png b/www/ico/undefined24t.png deleted file mode 100644 index 5def1d2febc1dfd9a104ce35bc214bed5ed44504..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3249 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 Q&;S4c07*qoM6N<$g6sA}HUIzs diff --git a/www/ico/undefined48b.png b/www/ico/undefined48b.png deleted file mode 100644 index 2b41ee695cd3efb97555f0501891686084e40341..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5659 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 B;D7)C diff --git a/www/ico/undefined48t.png b/www/ico/undefined48t.png deleted file mode 100644 index a8f0c83415d0f6d0d8615ae7432fa6a629a7cd12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3675 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 diff --git a/www/img/Thumbs.db b/www/img/Thumbs.db deleted file mode 100644 index 6313a7659f1de8a032f7e756f13593766272a433..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6656 zcmeI02~?BE7Jw&vARq+7rtAR$Wf24dQK5>aLf^v;iQ7}KvKbLk5P}F#P*D41Rcw`G z529EV7eKKEML-BHMLYQq98#iAd$Q~2rcdNJfZfS9^UgNUuOP4_n(>j&&-`W zQ(MD)n3XqHf_^71h=ls&3Wz%7J^}KWeo;k;2pN3cCzs3L-b4tpA7vE1fj7`r+CU$Y zA*BGg&*=mA6d+Xu7z5X%$h4159mX4&k3!%Rh78dxv=-9!NC-VWe9?pvGguAjJ&%=U zh}64EuM@Cdsmfbr+xI;4zQ4(cNEoair|;7r{682Eb`Uq@3s(E0HSiV!-rgF~uPS)K zk=CyUHHZdku^Uls|EY}a$37U(+u_=;4!X(Md4u3*aTfQ<(D{#j0`>tz=f4tMD+6Ny z+fCiumXaU-Q4louN2j~KN0M<8v)DSQNi~%-a0+<5h0W-iHumC0i z69G%W3a|!jfJp!@3%|q3fIZ*nkMom?D408;F zp{l9MRA*^uXeg;@X=}2y)mR!VTnK>#&yXn!6p8{%nW4-YvB*milaBO}K8awAh)e>B zNsw0{7)JyOv=%pbKnO%=Bb7#1P-K9@S(u>&5{XDA;Z}q8X80eGnG`i6+v!yGdA>B` zP?p`6)GRuCMqZi5{JJ)i$t%~#DJW`cY3qzN9dBlCF~Q!!k>ljdb(=Yh_vvhRj|E-} zz4?n4FZq0xpMOAL(CQ6g;Tt0&g;DWawy=bKibfRDP+VQdD*M%GDb;Z;5}nU4N%R()j4{lcuN7erlGszv}4xxvRV9HMWa@ zNN>&h#j@Yo#RR*EWHO0N!*&sf5deuvrWn~$)uzv*`G%?++ijtkUNZM?MUT-rst_jFlv zxRa7N+SQ?rQrk-lo^I-xD%)u7#9h{Y@7aYphgw>Vi_h(hG;z<`<8~;el1@ggptj?j`8yW!F$k7`0Qq+(Lwm zV%-AUD-Io}TKK(AvgzG7rQ`Kx++13BqJuHTE1~>)lTe&pV>iWo*WOJoJc)Szq$qxR zLtllfYRldyKghV7HiU-Ckw_pZ*tWBx(TdVq70j=0jR`$aHSS-PXX%?x*R3uIiMg0X z-6CE2v^>W6M&~B?>?DD+xa*99wN~q8w3heSa_dp=ORCxd><)JM0kfO3AW8L#Dd>KjI}0A;_Ny0uf|*{X|+vpBq>uH_9UtY8)H zh!i%qb(*>{4K^-mJ-32WBukaw8JwX*QdLCjUw3@q9tQjT{+VnYk{l1QLO5E7+|lQ- zI764S2I+s1!STE0 zFIs7ubsh$7~-WIR3>&VPAlQx#5(B_Z;c?fj>!x29bYKks~VR zL+T%X81^y#`fXe}>it)*)}zGAWPO>nw4rkK&&iVBXW|#%7Zw+$pm0m1bKTRSes{hzPwypFHPAa=bl{ze;nF`E2v=*}YjT zYGnDBShUsbXsGj;{X%bj?nxo7_IA~y=lt@OF`R2w{N|Dssl9v^pLW^viN#q40?)dP zoiBSF;Z{S-T?e$7}62-qD)>DC1jt>82dfIdwMLHLIap zFstCE1H0BHb zmwmOd6sr>FNbSI!#%Zqe5*nRPIM9-X@l8Ze?rHO-PcC0!q}lF!U|)9LUr%J9CXQVm zph6Frdu8%$uaj~V?z(aFngciTFP3-KaRi6Id;E2t*`;m!XY8+PIGk%&6V^gaWy@+< zs~3+?iLM}4?|w`rjLUSc5j%V~vo80%bM~SjZW!_QoV>UxO9NSH>|Lx0)}HRAXaiqR zppdx8gL$wh#!@;t_qtHza?&o!VwzUqiM{tOMnv5D1FP4s@mJy~iN8MX9|!lvquzhL zSuiB_f;j9Gx^Ct^G}2N0q^7MC_8IsD&<{>O!{CG|1a0ikuYq$x;cs>w_ymfC*XDUe nbi6xR1-cQiCwbQn1?%<)Ic-b!V_ko!0iQL#OBWaU*T}yCJLFkR diff --git a/www/img/about.png b/www/img/about.png deleted file mode 100644 index dec66d627617a46babdd1028960f0a29d3bdf9c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3261 zcmV;u3_|mXP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XU000XU0RWnu7ytkWKS@MER9Fd} zSPN`aRT}>9xzm~Hw3Je?lwx_*Dl!I$Gy=vA3O;s;#&^~1OV%JUMvZIZssu9~6m^%# zBFe5|*^ulKAC;;pRTB{fvNR~TLkoQXeGIgeX@ycdk9HpSp8fxG?-^#M)9J7$bM8Io z{QvpC@BHWW-%&W{aHUC6KmqFJb}IlbDwrnBvdhI$1JLx98z(~9W~ku|s%q7&^--7l zWUEhl3Oy!DiW?Z|a2M!O_ua2LZ07>ZUSx~v4JX3a#yGbuF0*xBrCOpzMG$^=RYh3p zrt2?dsqc)0(CZ4$h9Zfq*wk9m8;vgN3Bg_A2wx1EJ`YuL!J%4_t^y-^1l>IXs?uV& zvLmzY%7Ga+%dziXbovNbdE^rnYO8c~!MI)+myqIiGwyN;kKFxs+w3og!he7me-LtP z3yMnf;kUEwuykq;o zh@r>jAVtT-N4oiini@Ip%B-5E=iy~fH*D(QPc`)O1D(VA*`bIwtZ@zd%B*9VvZxPh zx_0*Gh(@|kH4Je0ODBg{Jl*9Rnx2<<U}F3F|$3;I%gXO#OL&xHq8T zIw8P#(siB3wB$@}iHZ6g?hR^dKI`MKp`F9}V|BN0IX)eAARVbBLQ>(Tw~v>>I?tip zcYF9p&4Yx1c8x@U8fJ+r;7tya3dsx|*}{1kZS3+~)C=D0+zf%NnD5IJj0Q z+t8(ZRP@ZZ1{py|dc!m-UJ^JM(|JQ@h}WGCaw=1jGEp%fIJ0rDl5GVsRKy}oR6$b4 zx-|&lmZioDTy*f-DZcx}C0Z-OZaOlAK>(CKKN;lkSDXgSRHh_lqLT1Pu%#0Qync!k zCaQ?dM{g#!Hy+ljwzSXb@W)|Lb==uKWQJ#ZJ#vS$VAAec~x#~67m)U4M%KWAdYX>dd@+a2DCLOuf^}2;GimD92-g zw3=xfokdoy46y;UX{2BfQemdm0T9d5JBgMRvY?_Vb(Cjd9r^3`9oIu2^YVEumyUVGH~HA6-@S29IDz z&M{VzQ^xq# zT#7BDN?xU{py4~4{hn+@C(Q0Z;OFbCN*jp;q2E1qVzLirfI}8xyLiYzgMfh>u#uI;pH@f(T%@c3392V$&Te zESQo54KZHQy5E}vx6R3Z%7{Q}62zQ1qAGEnri#bZuYI%m;f^4$2D@X~(@q<#sL0oM zw}jZo%@_W&dS2n3J6F#cP4!U5DI0@eHqg8aC&&NNOVo5@#TEZ^>wzua!e+n!iLQ`V v4Js=In+nActL}ew(Prv}K_PL7Puc$fUhFT+n_HyE00000NkvXXu0mjf@8Ld& diff --git a/www/img/add.png b/www/img/add.png deleted file mode 100644 index 00a71901ae354e8b7b9b6097f09df2c2c76dba33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2168 zcmV-;2#5EHP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XU000XU0RWnu7ytkR`bk7VR5%e` zR9$QoRTTbacJ_~-?QROT3soXYh@>$z7=oG-hz*MRqOncH2NR<)qCEKEqwSIyUkr~* zg=lzy2fCUDBTc9erHK)v2wF8&XtJ=CZmaFK+je(nc4qGJoI5+!^la|ld(OG%n{&@S z-!+H`p%^T^LokPW$rl@|CUV$`O~}Avg9E}c{-F=(ZWwd;q+yK>kQeGk2xxG4?j($X z0aC`BMoahOc=?I8qc1#|-nTcC%x;NC;zr%As|CAQx?R5Z~ z0veFOz%mGX2JzH;BS(H3yOXDinq`yE<3Ca4(!5usuO`pZ@!_sf3}O#^!6%EzEMnwx zFhx1=8D2Rx{&u76-xCBuYVh!6tw@P3Lv*pzU-lm~@J(OokwF|}RfFPC4wfjpKgHow zZhS;-XV7CxYaD2M=Ebi24@y0`R=&YEu76_S62tdxcC5lvcGF@6Gj|nd zX|m!yx%()dYki$=x)JGk8{$@Sy-RvkY>}<;4(v=HI$}xF zW)fLOlMe;GTx~4j=h9_CM?8{%<1HW)--b%PfSWVJsJSZ)p2FVjv#`vVj!T-Gk&d*W2^=Hx4p(4;OYz)>r)K2hz-$pWH;~U3|D!bK{OJV?6fFmpX1hi zOSn027iS4xhrun$H;9C_3H!D`AMVBX#S56LO=_^t_NUkEvfxYP(nM5EEt_R~`j#m~ z7jBmQlJ;{W=>YDJU}nAQF6(1TW}$@srmjlW0;ZNPUe-4uME~yg74b#oYr2-r%a$^1 zh_>pQ$uUI&zrool$&SlK*44>Njq@|e2TbAm9lz8yD%@mYruckx-LImP>pN6$tdOT% zt;=7NCDQ%Q#Ns#|%i}b!vBu@hX>|6F_RR`6S%k~J$DC~jicO2qvdLv3v{Q6`r+2^Z zzK##k%6dS(@ad6PqyNfF(}mhZ5Y5T)BIICblhoO+NHP>dIazQ00000J!HBLXT?6cCXnqEaoGP^9-NQbO;&7d7-M(xnrM z^d_PpsBG5y-tT|c`;9%ufAH_U$Iej>@;oOQbB=l6_cf=su9m!lZ44*|wB`-``Sa)F z$B(~%{~j6|nw*^6-Q8VXUESW^CK8F?zkeSd9$sHx|MuFL(i)~{c`W@l$lPEHOE4yLB2e*XOV>C>n2@$vor{o~`~(b3V*pFi*I?fv-iO6>x+zx3=9lxXlQu;{Q33k z*YDlCM<5WcUcKt)=O-#E%E`%DRaK>+pio#?Xk=vc?%g{a4#&^WpP8B2-Q67%6Qic4 zW@BUH>FG&NPv6|!Y-VN_78VvCAOGmlBWr7GS6A0tw{B@_YG!9=0{}2MICy@3e(~l1 z_QQFOG}1IPRaZ6EloS((fG&Q-`4dWl0K5T_zaIGOZvsfqvEKdxfkCf>LqfyCBO;@s zV`Agt6B3h>Q{JS$O-s+n#Ajva#3_KsYl-aX?SF`g3(yjb8328)tGT?k+`%RZzwjiKBH;4va`FlXt!}VW3m6^ z_@w^pw_l!iKLH4WCoea%%@aZ^WW`j3RS5WHMQ5W^mEENzh-NW(T$Q8!g0tLdm64~j zCtjfKC9_kdW`D9cuFq!rn%3Z3`A6(oefv5?nHX#OC4~x|;T#=(>MzN)MW#mj>sQkC zJWb4e>584_Q#XVZA6a$0{{D=zbgIUz&si$G{-H_T^!ZeC`WdZQJ(31V2asrW(c^%lTXr(5{0}G z{gt+JLLPw&7;V(06(N^w!WMO^hCIUmZ<%xVsTsjlFg|8k=B2F38)jOg|Yq}b+ zk*Ib;ZI0jpw%SX=a-guvWagp3EH0c$^z$TGqx5;XQW!~}AuHx_4YZzHRISq@0QMu! z4ruhMw9vO19*P4|R*6|02+#>&E6=Se#SM_;ReI7Af^`0tT&-R*Y~dhjN#}iXg1>zw}Sz$i3 zKhBmFApb4^N0$iypM&IIxT{m ze4@DsIHI3+{bIQ>LA_Mj;O2=ym;b=GW%u9j^rAu+LhD~A415{l~4gYI-jKjCdez?;Jk z-y+N1jHwfbqn$5NA>&={oiqTm=JW(v`uPhZ;6k#L)b%{-<3>Nw8objKGvfYx(W2w5e^oQe)KBQ_UI z03}B|$>m%d*AW0W(EJT2_;~L6*AB$9O(v&Abs&z12rWeZBhT;-oc+l$FSHWxqm$0*)GjjXj!`QKt6SY zXx(~_BIH-*;%Hi>m=s$UudF#WJ9QGsuD7XTo-XyuKg5uX$j@{wTsMX$NimW1ss<-X z;_oy@nF?$Wq;l5?75+KCLeI5ex#Dznt2B(4@iXv^jqu8MrR-?~WALC6f4!OeWWSm< z;i!Dz2axkniB?Fye_hR114mYs+9sxfS5-n`Zha8oZLd_M5QMwMzQY2yA@M=h8uj&F zOyFzYI1P7-w#rdsHQikkNXXVQSP&ITbVkis*w@xWP;DZfZTdGJ0u4L81Ui!>g}cT? z7!|dZ>`n|4Kr_lw%YPB|W8o(;0GgN03H0Mn8mx_N`46v<>OJPfo~^AxeoK#^=YRoF z|IA9=9p6$>W$Yw0=ic)=rrZGS0Ic$YnzuQkRLugVmVuID1phctF2sj3MaauR%mJ+J zh!L{_AscCnp|4ew;nlo3p+TE3+B@I;Efr4Fa$lRSq!1e;SIaDjf zMZqWbbFG-lx`R7GdM{{-)mG!`2>z7s2ctzlXE)vNrU<&hiu_)*4iPi#BVQJdUh2vQ z-^4$?%9RjKv+AqBawRi+pL;7qLKZ3q_oW~Ncs(yncPsUll2JT>5>P$dlm$OvAOvXaC5Dd zSgVmpR}bw6nX zWb*2g&wK7b<#w*{Q&pC(b1GMfoxg)AG)kM$#GJmCBXkzbfLzZrNWz1^0E?OmJy$Yv z`64(-8&r@a5%|ZBclXSOb`&V`#h+I308@5cs`^%+y_BX}7YdJljOr|99 zw>i2Y=El6IvUUQ}5+R8;VtCuj?I7!5@u4b7&#rTs)MP<0-ixL46|Iz&`}N23aiHtL z!Zr%jp6r|Y*)FPqj{$d+}|KZGi+%7^G<0$eqIE?Iq3^B$>kmEVH~S*l@Q`gWyE?!a$oZ=?qJ zV*wk(iHvae~3*gymiLU zDjzv+9y#d~Ih7JQ(-=876}fN{No0yzmOqbLHIG{JiP}hs+G>p2nTpywi8^44K9rB% z6#&?V0cZ>^Lr%18O0&5xx_cP}9R}D4FQYLaZbA_7Q{Xp~=6Pexm?RK?gADB+iV78` zaMGaijqT0`!34;jb;Q1t)?*cnYs{99M#b?ti7*$b^ESn$Jpo5!9K=IoD~{r1e)3;x zf;%V0i}=Q?IEg$?fuGYQq>aXj2gYml@rVinh^7Q?{{)`g1Y_O%uubk8eKD9fiLWGI zJM<=AOR##{V;mM%+9-<3SyWNrfdN>i%WaO%jn)JF;lq1eP)r?;H}Z=IXsBQTcl zZof$ljf*l)NZowf2uZV=PDP6+$M>a`uA~_&0PW0VG+5wTQPTKNg-PZF5WykYCi=_=OikGcV z=~iHoh{2=6@ap1tIw3sQa3)j##Uq()&Y3u!Xf#VUmtr=LMK<5FY=P8lq2_FnnQXDs zY;l$xNyQv#iyYZ!=Q;AJIf~6W$}>4Cr#Tpw+!d^k8iF?MK}2H*ppmL&DbMmgMDB#< z{>ahmTu@-+Q|+7)uM{)y{>QK4X>a-zcw-a1;=KJD)twq2`&f5+Ixt^}>SkZhQ#ZcF zS!ga@)5nfKzN+>)y&0$UFpmR-zO!Na)Zj3ed z$NLToUuW}Ue?>;aXWkC|0$KN-zuuy|4v*2&7H(B|fvcz2g2&V=ijd%=Gqf|zMgm?~ zIB>+IudN20rQFkJp_MkTW^a(}buP-|%hRz1{e0$~hLDMHu9{1w#9xAvd+rUg0Sd`vo+DyDol-*@qkZ+RG80OECDk!hxt}o=h--jL zHfqOiQgZ@D6b1R$6RI^@+#sM5BTL(R7T}#3_dl|zkuBfP2pv&m3{@}{Var#%M4#O~ zaHgSpPyD*+bkmVsf%UC$`EXQhkga(mwo2 zqBqhd(CxP{(i;)>;EdW38Fu>w(I4)nQi&A)?#OZgA-EulL(!U+)N}yo(1rAY;5m{5 z`4CZw{IYGM`W$&+5pphzT0GW0klH&L|URx|^y>>%}|e*2*gg zoyE(LY#-zV3xApt<(qKfs%d1_^SgtV$amr5R|c$7&-me$?ajodMw;T*%DQ8E0Q5q( zF7Ym*vUotE>=S`d$U;tAsyfe#WVTnRokiBN#NyZ}Xox-L?LGAX_-sH>t`J#$CU9pP z*%u~!&O%WbA$;si@S2UCK0`1L3Qn++hd7H2h)|G)i}L~$uLcBX=gyHfC=($;Is&Qjg6eyrsw2wSL$$Vy75r=4kZI7Q<#G5rvaZP+o=9L z8N)%99WaYoc`{})9W$Ct7OnJ)KXs5yZIetsQuq=3c~n4YA|4f!NgOXWA?)}} zr7ag`5T{D)^>#Nt?+GJPcFC@m3MIXaVr84oIhf9HAJ=Y*>M9iqEgLUh2C|4{Z%R9t zm}b&UI?`=KCP@+Dzxkj2j&%4a==Gbd^$G&_o1b1JN|>OP=RTK>)`4?R5>r0f1Wv>N z^V#^B=(zD2dCf=n5Z#BMT+Hm2!PvCpLYm#^TN{y`NU{%QpH_6zP9;YoBZc=P$@&cW z&S;{jBZbk1Qzs7*6A{8~4MFjn%}0^wko~a&-1sbKva!JR-0bG5Js=hdnYx z_#>Mene}_b=Ahs*GScafK*h`HMw9l^7~<8#<&RU#2HC626htk9&)nJTiVZ4tFP2^` zAkwT^9^KL2dbw(KXQR}e(5*I)^4`dyUeozAQZc;tYI#28XtCJ;i*&hA=%5??-ewoi z>f`0rtb_Op;%3Rm2sxG2YQk0pW^-_4CBoy0naZ{-8B&6BPB?h^mEC#?W_uj3N<*n0 z<2PAjBf=Mj==d#wUeLVB!9SLP7*au6yuWzi`54#?Ijw@6o4>nJroLjtw@ zmjK95b#`b`V_}2-4zittpS4%VLyUVrYPYd{vk0~ODtoIlXVcw$uj|i#J!;>6x!8Jj z$pCziJS0f-K|Sb(_SZ<>I1XgD$yaUZzQ>09pyKM5vXCBHMLNiTKKX8e|~+JQ7s<@f760C+KP*ydL|7V2>Y;JbE})V-mx3RJWBqmkxU z-7x6WnGNGd9lA;YV#vZo{K*zAyz*-Fs(2qO{?GXsh)o;>I0ImjgX!I@&=OsAWCaZf&7ne zccJ7=3K-zRv2BTDQs62a$rutir2!3UXPh3u1vdD6{?>c}4m;^?Ee>vX%U^WUUhZhHwf(;z_KOFCLI&O$pUVc7=n-2dk$2$p)C}=2P zLD&54c)#Iq>@47F>+S0wNbTtQfZav zF6A%-(l{n;tUya*XPr>qfRpf}x)-{%w+Bt7T()*R$IOP(F}B}D?u!+U+*04Qm+w!w zF`8$X^W>ROoiktY%^DNE8P$@{I=bpF*q`%@OjkI3ayBfPbT*-RcwWPIAN6_HxY;vr z=wr#T*kYmXpylhzuwF6Vn?HU?bxFL4>To%jOXK|dm9rmLK7V+XZ1(4chpypV!PVM!zqsGO zgYRO&e(?#fNS?*h!N`Q<=>jO8)Yt^lsOV(L=)QEfmC^00ye;%jTAD6&xsQAV# zp$cvDCDGiW=u48B*XEaGo7aMCDfUTDYi}I$i`G(I>o?clx_1k%r+G{|t*85}6|HBy z__4X3iG>Mm-~$<)H?l(biZ`+&WVbeQVzh)da}#blZ|0>q6mRCId2MYL;9m=E73L;6 zZxt2h7jG4p)^BZhJI_|y`~MYaQEZ2{O!G#1@Py+mZPw3e}}q{ zmizB#^3j(+00FFl=1rTd2W_48!*AQ*a=%K*kxC+8E44M0zdr4nvxxZG-RwLl(Jk%s z>uV=Hqw--l>g|ieE<{Odb%&||D{IH)&u_aw$Z)^7JfuL%R?&N9On=W^nv}i#!w!q# zWs0k`WggA4l?2PCYXL2Rluvlxrngyc5Wj!62^J+q+9yB!F>Nu3|1sm*@H^y%p z-*vbFumi6Fy8ld`0@<&^>7f)_I#gl*N}f^x9SN_j>}&z@w7-(40v^_!iW~}X$wl&% zrUR;M$zo-1xM*awtzBLap7#EM0-@&aRs_S~_(TX5^>Fv)$@zKI%rJUkwV&+MQtPEJ zJM{q5<}l~(QBmjDZr<-_sZ@xQ?$-ybj$~{EJ1AU8*<;T}f)vS3>AxQH85T;7G!uCZ z%25MN%kKFTWAUKa*6zf)2OxI6>kx;s(&J^`QfjGfr&+0Ma(WPpjRn!>VHt~pNGZsoF5;m?rSk)|RZ9SF&TDflS@zu6&^Q0fC+C2X zIyPF_2*nBe5|~9vzpISD!E^zJKQZjg%&E})`BO=_%$oy4imVKk_n~$snS(OBfe5)% zURMt#%L)zU&4t~hIDQJsJF(xgtOstTW+aq8(@@LGf0+pvG#fagx)Ri^`uvaTjm__w zoW80gQ`kT_deRwAV|Ul2N=Bg9Pj{Lx3k_QEUScQV>zWSoyUm*#7$DeSYiF$Lo#kwt zUb*CAd|QAMC^zq74NZs*Mu+L07L z&R5+Y+fB!?!Attf)F3d}Lahxh7Rq%mC)ooF7LhXv3q{DxR7K^#1&sY+UK?c2d{k`i z|5=C5+hvVw|51mX3@$rWy?iA*)q{W6p_cG&?f6ZX-MWi9+^wJU+TLv-z82nVTupMh zsKfk{z2=?zi#j~$7T#|?nsnKJcd}Np|NhsH?fnk`smK8V%IJE~2Int5X#cbq1FE2( z!m2a2fUozQcNukJOHhp7R_biV{iz^I_T-&*3cA4=tv->@kD&}z3`Dg7QA^N9vBI!H z4aJQVy&{;*M(H=2Yo#**!#YybLHVNST@Q9ialHpHE9G5j3e!P#e)5}^>47wEEEx6A z)(^69DUvZ|UX*Vr8v|zC89BQ;;9J1)ytc7~&6xM`ZeY}`1V&>qa2C+)oy^0WEPFPJ zLwu;EhUBTlwI5Wi#???exIDTS<%_zqq6MPLNH)?yR=>P{y5%WutL-An)AnrhmYMf$ zxM{?dmQ`s2rr`nYD(Yx2Vg-5rn%Q5}|gL@Daq6|)_5ecidQA^L_ zykB;`oyo#nYGmHVL3+oW{@GKIz!W;zv#^aa&=dzEI+lAPsi>2?>|%YzL+V&O`G(k)tq37mJ6d-zu_uI6Lq(Xl#M2FGFr(T2a(IvA zO^ZlMp)U>8$cj$OcqMd1buhC8_@$#mx1y1YmrrmB8zD6_Cc9&N%jfb?NJC?Y~dwJO&bGtqHbkiemN*8CSyS~g1JCII!DW%AT72)SZ--*hkI~YMG zf|?L8gfB7vJhqGnOZAdU@@HSzLMb1w7>)Tc5(K{UW&qs3v-U;o>&pk2gnRY=i-P@m zPULZku9aDDyLnKU5c$zJ`XGU=|7WI_|D$f{R>dg|az^ToXQ>vj_+0O4z2e$Tp#QdJ zsf|o=K$B3MuIWP`CJN!y37`Uu6S)yOqLKoo@l2IcMt-OAoIKjZJpjqz-Kw5r%Qo`0 zSNX`-k>qAX=@WK2bUy|mTUuI;B%?g-q>&s*gJoSmhm7|st{7)!(w&fh?>B)rcT5P6i4>Asm83yNf#8RaDfVHAfNA#6td20!nqBb^I0R=y zhn2xDKgye%JOEFTFn`=C&4k{V30M#RI{TRaPEU`glFDVOfJ0G*dF)M8%?bpW>c8qK zz$O6E(BY`Xi(>t1@mH`>L3k$D44=M?fQ7@2Jf%HPe38D2>~`E|A`Z`DwsW$DTLYer z;TZ59%O*+`r;9ife86fD?V}gVBIL!bD~`ym*0WVNDhkE5S2sm{*Kuy5zVre9yFNc~ zEa($rcnO8#D%JsAy;AFvxx38Y#ET*~{t=(HakSnzCSmlX7m_f~)6(Sm*mIS=Ty1W2+vClXC zQ2hJk#>?czuS2CcDQVY()V@|ek{6&uoh3olsjs_fi;th|tp%!IF?2hSN;qA;3Dao$ z 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 diff --git a/www/img/alert.png b/www/img/alert.png deleted file mode 100644 index b9cdd22f76ad98b173bf2100fbe0b9d344229aa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2307 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 diff --git a/www/img/downIcon.png b/www/img/downIcon.png deleted file mode 100644 index fbf28d21835f56264fd4ec7b9942f7bc8e86dd57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2145 zcmV-n2%h(eP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XU000XU0RWnu7ytkR<4Ht8R5%f3 zRb6aUMHK$#?%M5cmxW5Vh!B3FfhY!Lg_I|2(!P<9fYL}pCB~!=1Z)XLO^8rhgoGEP zVuc7P{}!-3KzP&eAP|DsCML??3(z)gvfXXFtb4nA@15g0b8ok;PBQn-oH^&a-^`rz zT}4EYc0eg>KarMkk5bE$KvNa4(c1K0s-iX-6}vNo{`Qx32q4dd9RQ&5cl}0n<77C_2nJkt5en9Dy-PBj#Fettp=f?&ZXb%Qw znwzVB11=1Fd4Rm(5%wdOyOzO!n%G?N8Qj-Fw>ainOG}Jx2Fozyhq?)z8~?GJA+!Lw zT63J|@la;`mM)ELW{oX8b8}}ekPzXqVQK({x-esBiP8p00J(YNIZC&8QhI+Uc@q=H z#)zc-j~TW@%rw|O&y>R=E4;U~He9iXz-)$WH30P(& zfGvwZY+j^ZS|ED~sgNZX$Kn3%%RGc6!eUeM;AYkcvL-PW$1eG3`y$Bgtd{&Bkze^ZRSnf?5-+3kBqQeui=#B(`mZ zipAKjVJ(~s#9lUIaU{n@zULA=ekZmz!HPu{YLie+jj3=bSrb>4mEwou!^ar=c)Qu2 ze)L?!qpOy0IM^>&t z;_wl(J^Ro>&yusVqcyw4!?N=dcoU44|GYqLdx8aR<0j z;u7Pgwd0ty&;^^aorh?Uk8Aj~H)v#SibmGGO~bFRGPcoOZRBwonjlB=o3!)b5#2@d zCVmAzmAd6Nt2%VCI1RcgMZ>Gt`CvO+IoZd>e^%9GPM?+J{tV~+#2%PRY*QsuiEG=G z>G+DCF;nU39iNn$nG*EpOsr?ao_?!GjXDOmN;nFoDaK9H?ft)L2K_hi-RZ*d-&qe9>~{mmLLIr z#v)PPz6iztn_(qBfqb14>0`HP`C^V!(xYVi{q+q4a#3>oPDTXQE(@%4{~@JMbW?wQ zqY+ryoq$bYn299POc}qT)Y5q@8vF~`Af*|ut%*y7%Q>riuibl&$?N05<;^4_G&}ZR XYXXeZ64l*G00000NkvXXu0mjfX&eyW diff --git a/www/img/download.png b/www/img/download.png deleted file mode 100644 index d363ff04091d55ccd9ef29f57f3b1f9b07965fac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2938 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 diff --git a/www/img/license.png b/www/img/license.png deleted file mode 100644 index d755f9b144d973761a3ef297fad6efdc76d4e107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2271 zcmV<52q5=~P)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XU000XU0RWnu7ytkSVM#*F1NiOOWWPOt}mYC&gYqPesj*5 zxicfQ*6@=61adjb;v=2Ss?|ypen3Ki>IfoSt)vzBc%meDMcK9|N91x+>#Q0WpUhld zz$i*;6Qrnm{f*@`t%T@!EFphdpG+M8asS3k494hK!CJ;b9^>G#d^$f{_-1Y2!`pU0 z(S=mnL5(Ce;y;c6#}+tut%NVn-T)R#vl}|C?1j-6j`O5M4pL|FU>6#feXA|bpFTXb z1-ZZU$*G$)s#jY1zCVAvf}>~EzLQrp4xZ7OvEL7~4*u}5CU3aqa4ua}Oqi?+)d>ou zp+`HpZdaAIXI~;0u?|hq-7#T zN=bQh#1mi=LV~cMR8dGu$V1!L=?`B`BVV$I1E7f29pR<{Kw7z$@iR1A<{71J3mp{T zOg)Yy_hr=kLn-77)^Ok0)UfFY?Rfz}hN0!e1t2Vm>l7w8%S#K2K*`VE8Bj;x=*6rM z<7>wzckreuCSZAL7xy8rq1D{8|I6#TFx2N@>O`+O1=GMQ2e-L{m;HFg!?17|(ueS8!$ggvF`{z4&s8mIn7ED1ayp*!+ z%{@y0R(7_YzEyaWRDFjW#Zne#i3U}-2#AGwf&EOcgA-f(@OhQZ!%@YVMpuW0^VduI zxvytL|IDrRrh~w69<`8+FRa*79MiT5?BGnhX^$}^g8#P=Aga=G4Xs3XU=yivACGg5 zV@Yy z{2(CiXcr&@B8n&qs2*(J3}P>a5QM6+t6N@R)Ijx)0KO%$ytvkTS=G{?#mI|Vh&PY_ zkb;2t1l=w?tf$W8gMf@>+J&h8al4~s^86i}>M8yEIJps3B3i6Qr1cK^B?9T{s2hmcFb z7>XXyh|8f{Clfz3n7~^aZQ7eoNGxwV9LL@XcG*>?p(Gz+|Cx7RVG;yP()mczQ8Sj0 zWU)-9Yj^3MT~tUp_EpocYr@3yeG6?i+hxL$(zZi&b^v+=4{m?(~|J{KZJwwA1)u@deF$Bg%|VzW#R+UqH)eL60=#vv|-f tVyF9Hg=Q%ApO1HA@1>7kJniXbmU}Kt;-`Dr$$J0*002ovPDHLkV1h&>Nl5?z diff --git a/www/img/logo.png b/www/img/logo.png deleted file mode 100644 index 4f66d1170d2f843105a7156fb36706cd6ea82c08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15752 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 diff --git a/www/img/masterchain_icon_48x48.png b/www/img/masterchain_icon_48x48.png deleted file mode 100644 index cd66da8e1bf284bc32eced5185ce1c5fdbae720a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3420 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 N002ovPDHLkV1l^j)KCBb diff --git a/www/img/upIcon.png b/www/img/upIcon.png deleted file mode 100644 index 933935b84b740d46635bfda91d889ff1155c69a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2218 zcmV;b2vzrqP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000ie000ie0hKEb8vpm}4xY)Im2pl_!pS1qbaWE@W1%x*wUj^|Vc_QU^4cPqK|151v*Os#;Q#8!gN-PYSdt-fQ;uAM3)kmI z$(Dc&&bcr-z5aiZjLvXLz3IhE612)x0uuGnzs{fzH|fUlL7Nr<+>8ApZbt*?c2>&j z&L!LN(2yVuJj93&!B&b#y5go(u6Szll9-NM6z66Ri{Y7GarOB*kvB4BP}HgXRJz|E z{5)>^4%*d^``~!r&Vk;}jUN#u6>|)Vq9AhA zS&)sa5N1=GOr|mCi>1IK+upp**X7ww*=HQM1mnVhyRiv)mI{Ky>H({20UZH0=x&Im z@58O=2o%h9)MW@MD~)w}ywKV5UXRwQ@Ahuc+ytnoiYl4i{%1lmb0R>Ctqlw`#uR}= z+XM_$h_2oR9^tU3{Y%i*MrmtTUEtC_*u|PGEp`jDkq}B|0se^iA(Z$PGz9P1*bO`0 z@S%~8-vYW?_d%CuKUkO!;pLlf^8{9nS%D)r8Q}Z;)J%(?JbG%Nr{hLlo=)4d8Bk3%a*_1B@|v zx3ya;8oY?{DuBWB_@k1PeYn|&EE}Q3OW?L|spu78wUEkbFN^nQ*NkMhU2hheYE^c= zxnC+&ZkX0a+BU1rx7A#fu+9$zz-RHiVhMXJPd$SQ!#`2|Q9U&%5d zKnf>mkS^Jz(e~Oi|H3p*ASuMQIWZ<%uRIXS9U%Kvw%hN2|0HPFTJOIuk*zoJcu4rF ztyiJ19GQgk*XPIZvwk>~`x)Jm7agM8^~1ruSs4y^B*z$|;Ya~-CJ%o7!=0leW1+Ju zxq$6wqB}ATea9&}Wh{(CZNTCfBlr7*hho9#s94BW z2W$@A&4~;S*u`vE(D3aKekKPjrbt0{H4OPdfvz9p%CNF^ZwnmmaCZ1wb+6Z - - - - - - - - - Recent - - - - - - - - - - - - - - - - - - - - - -

-
- - -
-
-
-
-
- - - - - - - - - - - - - - - - - - -
Latest {{currency}}{{filter}} transactions
TransactionDetailsAmountBlock time
- - - {{trans.tx_hash | characters:10}} - - - - {{trans.tx_hash | characters:10}} - - - - {{trans.tx_hash | characters:10}} - - - - {{trans.tx_hash | characters:10}} - - - - {{trans.tx_hash | characters:10}} - - - - {{trans.tx_hash | characters:10}} - - - - {{trans.formatted_price_per_coin}} ฿/{{currency}} - - {{trans.formatted_price_per_coin}} ฿/{{currency}} - - - {{trans.to_address}} - - - {{trans.to_address}} - - - - {{trans.formatted_amount}}{{trans.tx_time | date:'dd MMM HH:mm'}}
-
- -
-
    -
  • -
-
-
-
-
- -
-
- -
-
-
- - - - diff --git a/www/javascript_required.html b/www/javascript_required.html deleted file mode 100644 index 7c83477..0000000 --- a/www/javascript_required.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - Javascript disabled - - - - - -
-
- - - -
-
-
-

Javascript is disabled

-

Please enable javascript

-
-
-
-
- -
-
- - - diff --git a/www/js/BTCClientContext.js b/www/js/BTCClientContext.js deleted file mode 100644 index 1ccbd8f..0000000 --- a/www/js/BTCClientContext.js +++ /dev/null @@ -1,242 +0,0 @@ - - - -BTNClientContext.parseBase58Check = function (address) { - var bytes = Bitcoin.Base58.decode(address); - var end = bytes.length - 4; - var hash = bytes.slice(0, end); - var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true }); - if (checksum[0] != bytes[end] || - checksum[1] != bytes[end + 1] || - checksum[2] != bytes[end + 2] || - checksum[3] != bytes[end + 3]) - throw new Error("Wrong checksum"); - var version = hash.shift(); - return [version, hash]; -} - - -BTNClientContext.GetEckey = function (sec) { - var res = BTNClientContext.parseBase58Check(sec); - var version = res[0]; - var payload = res[1]; - var compressed = false; - if (payload.length > 32) { - payload.pop(); - compressed = true; - } - var eckey = new Bitcoin.ECKey(payload); - eckey.setCompressed(compressed); - return eckey; -} - - -BTNClientContext.parseScript = function (script) { - var newScript = new Bitcoin.Script(); - var s = script.split(" "); - for (var i in s) { - if (Bitcoin.Opcode.map.hasOwnProperty(s[i])) { - newScript.writeOp(Bitcoin.Opcode.map[s[i]]); - } else { - newScript.writeBytes(Crypto.util.hexToBytes(s[i])); - } - } - return newScript; -} -//creates string representation of the script object -BTNClientContext.dumpScript = function (script) { - var out = []; - for (var i = 0; i < script.chunks.length; i++) { - var chunk = script.chunks[i]; - var op = new Bitcoin.Opcode(chunk); - typeof chunk == 'number' ? out.push(op.toString()) : - out.push(Crypto.util.bytesToHex(chunk)); - } - return out.join(' '); -} - -//serialize to Bitcoin Block Explorer format -BTNClientContext.toBBE = function (sendTx) { - var buf = sendTx.serialize(); - var hash = Crypto.SHA256(Crypto.SHA256(buf, { asBytes: true }), { asBytes: true }); - - var r = {}; - r['hash'] = Crypto.util.bytesToHex(hash.reverse()); - r['ver'] = sendTx.version; - r['vin_sz'] = sendTx.ins.length; - r['vout_sz'] = sendTx.outs.length; - r['lock_time'] = sendTx.lock_time; - r['size'] = buf.length; - r['in'] = [] - r['out'] = [] - - for (var i = 0; i < sendTx.ins.length; i++) { - var txin = sendTx.ins[i]; - var hash = Crypto.util.base64ToBytes(txin.outpoint.hash); - var n = txin.outpoint.index; - var prev_out = { 'hash': Crypto.util.bytesToHex(hash.reverse()), 'n': n }; - var seq = txin.sequence; - - if (n == 4294967295) { - var cb = Crypto.util.bytesToHex(txin.script.buffer); - r['in'].push({ 'prev_out': prev_out, 'coinbase': cb, 'sequence': seq }); - } else { - var ss = BTNClientContext.dumpScript(txin.script); - r['in'].push({ 'prev_out': prev_out, 'scriptSig': ss, 'sequence': seq }); - } - } - - for (var i = 0; i < sendTx.outs.length; i++) { - var txout = sendTx.outs[i]; - var bytes = txout.value.slice(0); - var fval = parseFloat(Bitcoin.Util.formatValue(bytes.reverse())); - var value = fval.toFixed(8); - var spk = BTNClientContext.dumpScript(txout.script); - r['out'].push({ 'value': value, 'scriptPubKey': spk }); - } - - return JSON.stringify(r, null, 4); -}; - - -//deserialize from Bitcoin Block Explorer format -BTNClientContext.fromBBE = function (text) { - var sendTx = new Bitcoin.Transaction(); - var r = JSON.parse(text); - if (!r) - return sendTx; - var tx_ver = r['ver']; - var vin_sz = r['vin_sz']; - - for (var i = 0; i < vin_sz; i++) { - var txi = r['in'][i]; - var hash = Crypto.util.hexToBytes(txi['prev_out']['hash']); - var n = txi['prev_out']['n']; - - if (txi['coinbase']) - var script = Crypto.util.hexToBytes(txi['coinbase']); - else - var script = BTNClientContext.parseScript(txi['scriptSig']); - - var seq = txi['sequence'] === undefined ? 4294967295 : txi['sequence']; - - var txin = new Bitcoin.TransactionIn({ - outpoint: { - hash: Crypto.util.bytesToBase64(hash.reverse()), - index: n - }, - script: new Bitcoin.Script(script), - sequence: seq - }); - sendTx.addInput(txin); - } - - var vout_sz = r['vout_sz']; - for (var i = 0; i < vout_sz; i++) { - var txo = r['out'][i]; - var fval = parseFloat(txo['value']); - var value = new BigInteger('' + Math.round(fval * 1e8), 10); - var script = BTNClientContext.parseScript(txo['scriptPubKey']); - - if (value instanceof BigInteger) { - value = value.toByteArrayUnsigned().reverse(); - while (value.length < 8) value.push(0); - } - - var txout = new Bitcoin.TransactionOut({ - value: value, - script: new Bitcoin.Script(script) - }); - - sendTx.addOutput(txout); - } - sendTx.lock_time = r['lock_time']; - return sendTx; -}; - - -function u8(f) { return uint(f, 1); } -function u16(f) { return uint(f, 2); } -function u32(f) { return uint(f, 4); } -function u64(f) { return uint(f, 8); } -function uint(f, size) { - if (f.length < size) - return 0; - var bytes = f.slice(0, size); - var pos = 1; - var n = 0; - for (var i = 0; i < size; i++) { - var b = f.shift(); - n += b * pos; - pos *= 256; - } - return size <= 4 ? n : bytes; -} - -BTNClientContext.Signing.deserialize = function (bytes) { - var sendTx = new Bitcoin.Transaction(); - - var f = bytes.slice(0); - var tx_ver = u32(f); - var vin_sz = readVarInt(f); - if (errv(vin_sz)) - return null; - - for (var i = 0; i < vin_sz; i++) { - var op = readBuffer(f, 32); - var n = u32(f); - var script = readString(f); - var seq = u32(f); - var txin = new Bitcoin.TransactionIn({ - outpoint: { - hash: Crypto.util.bytesToBase64(op), - index: n - }, - script: new Bitcoin.Script(script), - sequence: seq - }); - sendTx.addInput(txin); - } - - var vout_sz = readVarInt(f); - - if (errv(vout_sz)) - return null; - - for (var i = 0; i < vout_sz; i++) { - var value = u64(f); - var script = readString(f); - - var txout = new Bitcoin.TransactionOut({ - value: value, - script: new Bitcoin.Script(script) - }); - - sendTx.addOutput(txout); - } - var lock_time = u32(f); - sendTx.lock_time = lock_time; - return sendTx; -}; - -function readVarInt(f) { - var t = u8(f); - if (t == 0xfd) return u16(f); else - if (t == 0xfe) return u32(f); else - if (t == 0xff) return u64(f); else - return t; -} -function readString(f) { - var len = readVarInt(f); - if (errv(len)) return []; - return readBuffer(f, len); -} -function readBuffer(f, size) { - var res = f.slice(0, size); - for (var i = 0; i < size; i++) f.shift(); - return res; -} - -function errv(val) { - return (val instanceof BigInteger || val > 0xffff); -} \ No newline at end of file diff --git a/www/js/BitcoinJS/address.js b/www/js/BitcoinJS/address.js deleted file mode 100644 index 3013764..0000000 --- a/www/js/BitcoinJS/address.js +++ /dev/null @@ -1,57 +0,0 @@ -Bitcoin.Address = function (bytes) { - if ("string" == typeof bytes) { - bytes = Bitcoin.Address.decodeString(bytes); - } - this.hash = bytes; - - this.version = 0x00; -}; - -/** - * Serialize this object as a standard Bitcoin address. - * - * Returns the address as a base58-encoded string in the standardized format. - */ -Bitcoin.Address.prototype.toString = function () { - // Get a copy of the hash - var hash = this.hash.slice(0); - - // Version - hash.unshift(this.version); - - var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); - - var bytes = hash.concat(checksum.slice(0,4)); - - return Bitcoin.Base58.encode(bytes); -}; - -Bitcoin.Address.prototype.getHashBase64 = function () { - return Crypto.util.bytesToBase64(this.hash); -}; - -/** - * Parse a Bitcoin address contained in a string. - */ -Bitcoin.Address.decodeString = function (string) { - var bytes = Bitcoin.Base58.decode(string); - - var hash = bytes.slice(0, 21); - - var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); - - if (checksum[0] != bytes[21] || - checksum[1] != bytes[22] || - checksum[2] != bytes[23] || - checksum[3] != bytes[24]) { - throw "Checksum validation failed!"; - } - - var version = hash.shift(); - - if (version != 0) { - throw "Version "+version+" not supported!"; - } - - return hash; -}; diff --git a/www/js/BitcoinJS/base58.js b/www/js/BitcoinJS/base58.js deleted file mode 100644 index 9313c55..0000000 --- a/www/js/BitcoinJS/base58.js +++ /dev/null @@ -1,71 +0,0 @@ -(function (Bitcoin) { - Bitcoin.Base58 = { - alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", - validRegex: /^[1-9A-HJ-NP-Za-km-z]+$/, - base: BigInteger.valueOf(58), - - /** - * Convert a byte array to a base58-encoded string. - * - * Written by Mike Hearn for BitcoinJ. - * Copyright (c) 2011 Google Inc. - * - * Ported to JavaScript by Stefan Thomas. - */ - encode: function (input) { - var bi = BigInteger.fromByteArrayUnsigned(input); - var chars = []; - - while (bi.compareTo(B58.base) >= 0) { - var mod = bi.mod(B58.base); - chars.unshift(B58.alphabet[mod.intValue()]); - bi = bi.subtract(mod).divide(B58.base); - } - chars.unshift(B58.alphabet[bi.intValue()]); - - // Convert leading zeros too. - for (var i = 0; i < input.length; i++) { - if (input[i] == 0x00) { - chars.unshift(B58.alphabet[0]); - } else break; - } - - return chars.join(''); - }, - - /** - * Convert a base58-encoded string to a byte array. - * - * Written by Mike Hearn for BitcoinJ. - * Copyright (c) 2011 Google Inc. - * - * Ported to JavaScript by Stefan Thomas. - */ - decode: function (input) { - var bi = BigInteger.valueOf(0); - var leadingZerosNum = 0; - for (var i = input.length - 1; i >= 0; i--) { - var alphaIndex = B58.alphabet.indexOf(input[i]); - if (alphaIndex < 0) { - throw "Invalid character"; - } - bi = bi.add(BigInteger.valueOf(alphaIndex) - .multiply(B58.base.pow(input.length - 1 -i))); - - // This counts leading zero bytes - if (input[i] == "1") leadingZerosNum++; - else leadingZerosNum = 0; - } - var bytes = bi.toByteArrayUnsigned(); - - // Add leading zeros - while (leadingZerosNum-- > 0) bytes.unshift(0); - - return bytes; - } - }; - - var B58 = Bitcoin.Base58; -})( - 'undefined' != typeof Bitcoin ? Bitcoin : module.exports -); diff --git a/www/js/BitcoinJS/bitcoin.js b/www/js/BitcoinJS/bitcoin.js deleted file mode 100644 index e14d36f..0000000 --- a/www/js/BitcoinJS/bitcoin.js +++ /dev/null @@ -1,175 +0,0 @@ -(function (exports) { - var Bitcoin = exports; - - if ('object' !== typeof module) { - Bitcoin.EventEmitter = EventEmitter; - } -})( - 'object' === typeof module ? module.exports : (window.Bitcoin = {}) -); - -/* - function makeKeypair() - { - // Generate private key - var n = ecparams.getN(); - var n1 = n.subtract(BigInteger.ONE); - var r = new BigInteger(n.bitLength(), rng); - - var privateKey = r.mod(n1).add(BigInteger.ONE); - - // Generate public key - var G = ecparams.getG(); - var publicPoint = G.multiply(privateKey); - - return {priv: privateKey, pubkey: publicPoint}; - }; - - function serializeTransaction(tx) - { - var buffer = []; - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.version)])); - buffer = buffer.concat(numToVarInt(tx.ins.length)); - for (var i = 0; i < tx.ins.length; i++) { - var txin = tx.ins[i]; - buffer = buffer.concat(Crypto.util.base64ToBytes(txin.outpoint.hash)); - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.index)])); - var scriptBytes = Crypto.util.base64ToBytes(txin.script); - buffer = buffer.concat(numToVarInt(scriptBytes.length)); - buffer = buffer.concat(scriptBytes); - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)])); - } - buffer = buffer.concat(numToVarInt(tx.outs.length)); - for (var i = 0; i < tx.outs.length; i++) { - var txout = tx.outs[i]; - var valueHex = (new BigInteger(txout.value, 10)).toString(16); - while (valueHex.length < 16) valueHex = "0" + valueHex; - buffer = buffer.concat(Crypto.util.hexToBytes(valueHex)); - var scriptBytes = Crypto.util.base64ToBytes(txout.script); - buffer = buffer.concat(numToVarInt(scriptBytes.length)); - buffer = buffer.concat(scriptBytes); - } - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.lock_time)])); - - return buffer; - }; - - var OP_CODESEPARATOR = 171; - - var SIGHASH_ALL = 1; - var SIGHASH_NONE = 2; - var SIGHASH_SINGLE = 3; - var SIGHASH_ANYONECANPAY = 80; - - function hashTransactionForSignature(scriptCode, tx, inIndex, hashType) - { - // TODO: We need to actually deep copy here - var txTmp = tx; - - // In case concatenating two scripts ends up with two codeseparators, - // or an extra one at the end, this prevents all those possible incompatibilities. - scriptCode = scriptCode.filter(function (val) { - return val !== OP_CODESEPARATOR; - }); - - // Blank out other inputs' signatures - for (var i = 0; i < txTmp.ins.length; i++) { - txTmp.ins[i].script = Crypto.util.bytesToBase64([]); - } - txTmp.ins[inIndex].script = Crypto.util.bytesToBase64(scriptCode); - - // Blank out some of the outputs - if ((hashType & 0x1f) == SIGHASH_NONE) { - txTmp.outs = []; - - // Let the others update at will - for (var i = 0; i < txTmp.ins.length; i++) - if (i != inIndex) - txTmp.ins[i].sequence = 0; - } else if ((hashType & 0x1f) == SIGHASH_SINGLE) { - // TODO: Implement - } - - // Blank out other inputs completely, not recommended for open transactions - if (hashType & SIGHASH_ANYONECANPAY) { - txTmp.ins = [txTmp.ins[inIndex]]; - } - - var buffer = serializeTransaction(txTmp); - - buffer.concat(Crypto.util.wordsToBytes([parseInt(hashType)])); - - console.log(buffer); - - return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); - }; - - function verifyTransactionSignature(tx) { - var hash = hashTransactionForSignature([], tx, 0, 0); - return Crypto.util.bytesToHex(hash); - }; - - function numToVarInt(i) - { - // TODO: THIS IS TOTALLY UNTESTED! - if (i < 0xfd) { - // unsigned char - return [i]; - } else if (i <= 1<<16) { - // unsigned short (LE) - return [0xfd, i >>> 8, i & 255]; - } else if (i <= 1<<32) { - // unsigned int (LE) - return [0xfe].concat(Crypto.util.wordsToBytes([i])); - } else { - // unsigned long long (LE) - return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i])); - } - }; - - var testTx = { - "version":"1", - "lock_time":"0", - "block": { - "hash":"N/A", - "height":115806 - }, - "index":6, - "hash":"WUFzjKubG1kqfJWMb4qZdlhU2F3l5NGXN7AUg8Jwl14=", - "ins":[{ - "outpoint":{ - "hash":"nqcbMM1oRhfLdZga11q7x0CpUMujm+vtxHXO9V0gnwE=", - "index":0 - }, - "script":"RzBEAiB2XXkx1pca9SlfCmCGNUVf+h2sAFBttcxG1VnypIcvEgIgXrOp7LSdYBYp3nPsQAz8BOLD3K4pAlXfZImP1rkzk2EBQQRi7NcODzNfnVqLtG79Axp5UF6EhFIhCmzqKqssfKpfCIOmzCuXEeDFUFvFzeGLJx5N+wp2qRS1TqYezGD3yERk", - "sequence":4294967295 - }], - "outs":[{ - "value":"3000000000", - "script":"dqkUBLZwqhAPRVgZvwI8MN5gLHbU8NOIrA==" - },{ - "value":"25937000000", - "script":"dqkUQ82gJ0O5vOBg6yK5/yorLLV5zLKIrA==" - }] - }; - - TODO: Make this stuff into test cases ;) - $(function () { - var key = new Bitcoin.ECKey(Crypto.util.hexToBytes("5c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4a")); - key = new Bitcoin.ECKey(Crypto.util.hexToBytes("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19")); - //console.log(key.getBitcoinAddress().toString()); - //var message = Crypto.util.hexToBytes("2aec28d323ee7b06a799d540d224b351161fe48967174ca5e43164e86137da11"); - //message = [0]; - //var out = key.sign(message); - //console.log("pubkey: "+Crypto.util.bytesToHex(key.getPub())); - //console.log("sig: "+Crypto.util.bytesToHex(out)); - - //console.log(key.verify(message, out)); - - //console.log(Bitcoin.ECDSA.verify(message, Crypto.util.hexToBytes("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d"), Crypto.util.hexToBytes("0401de173aa944eacf7e44e5073baca93fb34fe4b7897a1c82c92dfdc8a1f75ef58cd1b06e8052096980cb6e1ad6d3df143c34b3d7394bae2782a4df570554c2fb"))); - - //console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("230aba77ccde46bb17fcb0295a92c0cc42a6ea9f439aaadeb0094625f49e6ed8"), Crypto.util.hexToBytes("3046022100a3ee5408f0003d8ef00ff2e0537f54ba09771626ff70dca1f01296b05c510e85022100d4dc70a5bb50685b65833a97e536909a6951dd247a2fdbde6688c33ba6d6407501"),Crypto.util.hexToBytes("04a19c1f07c7a0868d86dbb37510305843cc730eb3bea8a99d92131f44950cecd923788419bfef2f635fad621d753f30d4b4b63b29da44b4f3d92db974537ad5a4"))); - //console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("c2c75bb77d7a5acddceb1d45ceef58e7451fd0d3abc9d4c16df7848eefafe00d"), Crypto.util.hexToBytes("3045022100ff9362dadcbf1f6ef954bc8eb27144bbb4f49abd32be1eb04c311151dcf4bcf802205112c2ca6a25aefb8be98bf460c5a9056c01253f31e118d80b81ec9604e3201a01"),Crypto.util.hexToBytes("04fe62ce7892ec209310c176ef7f06565865e286e8699e884603657efa9aa51086785099d544d4e04f1f7b4b065205c1783fade8daf4ba1e0d1962292e8eb722cd"))); - }); - // -*/ diff --git a/www/js/BitcoinJS/crypto-js/crypto-min.js b/www/js/BitcoinJS/crypto-js/crypto-min.js deleted file mode 100644 index dc5b80d..0000000 --- a/www/js/BitcoinJS/crypto-js/crypto-min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Crypto-JS v2.0.0 - * http://code.google.com/p/crypto-js/ - * Copyright (c) 2009, Jeff Mott. All rights reserved. - * http://code.google.com/p/crypto-js/wiki/License - */ -(function(){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var d=window.Crypto={};var a=d.util={rotl:function(h,g){return(h<>>(32-g))},rotr:function(h,g){return(h<<(32-g))|(h>>>g)},endian:function(h){if(h.constructor==Number){return a.rotl(h,8)&16711935|a.rotl(h,24)&4278255360}for(var g=0;g0;h--){g.push(Math.floor(Math.random()*256))}return g},bytesToWords:function(h){for(var k=[],j=0,g=0;j>>5]|=h[j]<<(24-g%32)}return k},wordsToBytes:function(i){for(var h=[],g=0;g>>5]>>>(24-g%32))&255)}return h},bytesToHex:function(g){for(var j=[],h=0;h>>4).toString(16));j.push((g[h]&15).toString(16))}return j.join("")},hexToBytes:function(h){for(var g=[],i=0;i>>6*(3-k))&63))}else{g.push("=")}}}return g.join("")},base64ToBytes:function(h){if(typeof atob=="function"){return e.stringToBytes(atob(h))}h=h.replace(/[^A-Z0-9+\/]/ig,"");for(var g=[],j=0,k=0;j>>(6-k*2)))}return g}};d.mode={};var b=d.charenc={};var f=b.UTF8={stringToBytes:function(g){return e.stringToBytes(unescape(encodeURIComponent(g)))},bytesToString:function(g){return decodeURIComponent(escape(e.bytesToString(g)))}};var e=b.Binary={stringToBytes:function(j){for(var g=[],h=0;h>> (32 - b)); - }, - - // Bit-wise rotate right - rotr: function (n, b) { - return (n << (32 - b)) | (n >>> b); - }, - - // Swap big-endian to little-endian and vice versa - endian: function (n) { - - // If number given, swap endian - if (n.constructor == Number) { - return util.rotl(n, 8) & 0x00FF00FF | - util.rotl(n, 24) & 0xFF00FF00; - } - - // Else, assume array and swap all items - for (var i = 0; i < n.length; i++) - n[i] = util.endian(n[i]); - return n; - - }, - - // Generate an array of any length of random bytes - randomBytes: function (n) { - for (var bytes = []; n > 0; n--) - bytes.push(Math.floor(Math.random() * 256)); - return bytes; - }, - - // Convert a byte array to big-endian 32-bit words - bytesToWords: function (bytes) { - for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) - words[b >>> 5] |= bytes[i] << (24 - b % 32); - return words; - }, - - // Convert big-endian 32-bit words to a byte array - wordsToBytes: function (words) { - for (var bytes = [], b = 0; b < words.length * 32; b += 8) - bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); - return bytes; - }, - - // Convert a byte array to a hex string - bytesToHex: function (bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(""); - }, - - // Convert a hex string to a byte array - hexToBytes: function (hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; - }, - - // Convert a byte array to a base-64 string - bytesToBase64: function (bytes) { - - // Use browser-native function if it exists - if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes)); - - for(var base64 = [], i = 0; i < bytes.length; i += 3) { - var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; - for (var j = 0; j < 4; j++) { - if (i * 8 + j * 6 <= bytes.length * 8) - base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); - else base64.push("="); - } - } - - return base64.join(""); - - }, - - // Convert a base-64 string to a byte array - base64ToBytes: function (base64) { - - // Use browser-native function if it exists - if (typeof atob == "function") return Binary.stringToBytes(atob(base64)); - - // Remove non-base-64 characters - base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); - - for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) { - if (imod4 == 0) continue; - bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) | - (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); - } - - return bytes; - - } - -}; - -// Crypto mode namespace -Crypto.mode = {}; - -// Crypto character encodings -var charenc = Crypto.charenc = {}; - -// UTF-8 encoding -var UTF8 = charenc.UTF8 = { - - // Convert a string to a byte array - stringToBytes: function (str) { - return Binary.stringToBytes(unescape(encodeURIComponent(str))); - }, - - // Convert a byte array to a string - bytesToString: function (bytes) { - return decodeURIComponent(escape(Binary.bytesToString(bytes))); - } - -}; - -// Binary encoding -var Binary = charenc.Binary = { - - // Convert a string to a byte array - stringToBytes: function (str) { - for (var bytes = [], i = 0; i < str.length; i++) - bytes.push(str.charCodeAt(i)); - return bytes; - }, - - // Convert a byte array to a string - bytesToString: function (bytes) { - for (var str = [], i = 0; i < bytes.length; i++) - str.push(String.fromCharCode(bytes[i])); - return str.join(""); - } - -}; - -})(); diff --git a/www/js/BitcoinJS/crypto-js/ripemd160.js b/www/js/BitcoinJS/crypto-js/ripemd160.js deleted file mode 100644 index ff4b2a6..0000000 --- a/www/js/BitcoinJS/crypto-js/ripemd160.js +++ /dev/null @@ -1,170 +0,0 @@ -/*! - * Crypto-JS v2.0.0 - * http://code.google.com/p/crypto-js/ - * Copyright (c) 2009, Jeff Mott. All rights reserved. - * http://code.google.com/p/crypto-js/wiki/License - * - * A JavaScript implementation of the RIPEMD-160 Algorithm - * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ - * Ported to Crypto-JS by Stefan Thomas. - */ - -(function () { - // Shortcuts - var C = Crypto, - util = C.util, - charenc = C.charenc, - UTF8 = charenc.UTF8, - Binary = charenc.Binary; - - // Convert a byte array to little-endian 32-bit words - util.bytesToLWords = function (bytes) { - - var output = Array(bytes.length >> 2); - for (var i = 0; i < output.length; i++) - output[i] = 0; - for (var i = 0; i < bytes.length * 8; i += 8) - output[i>>5] |= (bytes[i / 8] & 0xFF) << (i%32); - return output; - }; - - // Convert little-endian 32-bit words to a byte array - util.lWordsToBytes = function (words) { - var output = []; - for (var i = 0; i < words.length * 32; i += 8) - output.push((words[i>>5] >>> (i % 32)) & 0xff); - return output; - }; - - // Public API - var RIPEMD160 = C.RIPEMD160 = function (message, options) { - var digestbytes = util.lWordsToBytes(RIPEMD160._rmd160(message)); - return options && options.asBytes ? digestbytes : - options && options.asString ? Binary.bytesToString(digestbytes) : - util.bytesToHex(digestbytes); - }; - - // The core - RIPEMD160._rmd160 = function (message) - { - // Convert to byte array - if (message.constructor == String) message = UTF8.stringToBytes(message); - - var x = util.bytesToLWords(message), - len = message.length * 8; - - /* append padding */ - x[len >> 5] |= 0x80 << (len % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var h0 = 0x67452301; - var h1 = 0xefcdab89; - var h2 = 0x98badcfe; - var h3 = 0x10325476; - var h4 = 0xc3d2e1f0; - - for (var i = 0; i < x.length; i += 16) { - var T; - var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4; - var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4; - for (var j = 0; j <= 79; ++j) { - T = safe_add(A1, rmd160_f(j, B1, C1, D1)); - T = safe_add(T, x[i + rmd160_r1[j]]); - T = safe_add(T, rmd160_K1(j)); - T = safe_add(bit_rol(T, rmd160_s1[j]), E1); - A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T; - T = safe_add(A2, rmd160_f(79-j, B2, C2, D2)); - T = safe_add(T, x[i + rmd160_r2[j]]); - T = safe_add(T, rmd160_K2(j)); - T = safe_add(bit_rol(T, rmd160_s2[j]), E2); - A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T; - } - T = safe_add(h1, safe_add(C1, D2)); - h1 = safe_add(h2, safe_add(D1, E2)); - h2 = safe_add(h3, safe_add(E1, A2)); - h3 = safe_add(h4, safe_add(A1, B2)); - h4 = safe_add(h0, safe_add(B1, C2)); - h0 = T; - } - return [h0, h1, h2, h3, h4]; - } - - function rmd160_f(j, x, y, z) - { - return ( 0 <= j && j <= 15) ? (x ^ y ^ z) : - (16 <= j && j <= 31) ? (x & y) | (~x & z) : - (32 <= j && j <= 47) ? (x | ~y) ^ z : - (48 <= j && j <= 63) ? (x & z) | (y & ~z) : - (64 <= j && j <= 79) ? x ^ (y | ~z) : - "rmd160_f: j out of range"; - } - function rmd160_K1(j) - { - return ( 0 <= j && j <= 15) ? 0x00000000 : - (16 <= j && j <= 31) ? 0x5a827999 : - (32 <= j && j <= 47) ? 0x6ed9eba1 : - (48 <= j && j <= 63) ? 0x8f1bbcdc : - (64 <= j && j <= 79) ? 0xa953fd4e : - "rmd160_K1: j out of range"; - } - function rmd160_K2(j) - { - return ( 0 <= j && j <= 15) ? 0x50a28be6 : - (16 <= j && j <= 31) ? 0x5c4dd124 : - (32 <= j && j <= 47) ? 0x6d703ef3 : - (48 <= j && j <= 63) ? 0x7a6d76e9 : - (64 <= j && j <= 79) ? 0x00000000 : - "rmd160_K2: j out of range"; - } - var rmd160_r1 = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - ]; - var rmd160_r2 = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - ]; - var rmd160_s1 = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - ]; - var rmd160_s2 = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - ]; - - /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - function safe_add(x, y) - { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); - } - - /* - * Bitwise rotate a 32-bit number to the left. - */ - function bit_rol(num, cnt) - { - return (num << cnt) | (num >>> (32 - cnt)); - } -})(); diff --git a/www/js/BitcoinJS/crypto-js/sha256-min.js b/www/js/BitcoinJS/crypto-js/sha256-min.js deleted file mode 100644 index d3a4118..0000000 --- a/www/js/BitcoinJS/crypto-js/sha256-min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Crypto-JS v2.0.0 - * http://code.google.com/p/crypto-js/ - * Copyright (c) 2009, Jeff Mott. All rights reserved. - * http://code.google.com/p/crypto-js/wiki/License - */ -(function(){var g=Crypto,b=g.util,c=g.charenc,f=c.UTF8,e=c.Binary;var a=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];var d=g.SHA256=function(j,h){var i=b.wordsToBytes(d._sha256(j));return h&&h.asBytes?i:h&&h.asString?e.bytesToString(i):b.bytesToHex(i)};d._sha256=function(q){if(q.constructor==String){q=f.stringToBytes(q)}var y=b.bytesToWords(q),z=q.length*8,r=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],s=[],K,J,I,G,F,E,D,C,B,A,p,o;y[z>>5]|=128<<(24-z%32);y[((z+64>>9)<<4)+15]=z;for(var B=0;B>>7))^((n<<14)|(n>>>18))^(n>>>3),L=((u<<15)|(u>>>17))^((u<<13)|(u>>>19))^(u>>>10);s[A]=M+(s[A-7]>>>0)+L+(s[A-16]>>>0)}var t=F&E^~F&D,k=K&J^K&I^J&I,x=((K<<30)|(K>>>2))^((K<<19)|(K>>>13))^((K<<10)|(K>>>22)),v=((F<<26)|(F>>>6))^((F<<21)|(F>>>11))^((F<<7)|(F>>>25));p=(C>>>0)+v+t+(a[A])+(s[A]>>>0);o=x+k;C=D;D=E;E=F;F=G+p;G=I;I=J;J=K;K=p+o}r[0]+=K;r[1]+=J;r[2]+=I;r[3]+=G;r[4]+=F;r[5]+=E;r[6]+=D;r[7]+=C}return r};d._blocksize=16})(); \ No newline at end of file diff --git a/www/js/BitcoinJS/crypto-js/sha256.js b/www/js/BitcoinJS/crypto-js/sha256.js deleted file mode 100644 index c5a2d01..0000000 --- a/www/js/BitcoinJS/crypto-js/sha256.js +++ /dev/null @@ -1,133 +0,0 @@ -/*! - * Crypto-JS v2.0.0 - * http://code.google.com/p/crypto-js/ - * Copyright (c) 2009, Jeff Mott. All rights reserved. - * http://code.google.com/p/crypto-js/wiki/License - */ -(function(){ - -// Shortcuts -var C = Crypto, - util = C.util, - charenc = C.charenc, - UTF8 = charenc.UTF8, - Binary = charenc.Binary; - -// Constants -var K = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; - -// Public API -var SHA256 = C.SHA256 = function (message, options) { - var digestbytes = util.wordsToBytes(SHA256._sha256(message)); - return options && options.asBytes ? digestbytes : - options && options.asString ? Binary.bytesToString(digestbytes) : - util.bytesToHex(digestbytes); -}; - -// The core -SHA256._sha256 = function (message) { - - // Convert to byte array - if (message.constructor == String) message = UTF8.stringToBytes(message); - /* else, assume byte array already */ - - var m = util.bytesToWords(message), - l = message.length * 8, - H = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ], - w = [], - a, b, c, d, e, f, g, h, i, j, - t1, t2; - - // Padding - m[l >> 5] |= 0x80 << (24 - l % 32); - m[((l + 64 >> 9) << 4) + 15] = l; - - for (var i = 0; i < m.length; i += 16) { - - a = H[0]; - b = H[1]; - c = H[2]; - d = H[3]; - e = H[4]; - f = H[5]; - g = H[6]; - h = H[7]; - - for (var j = 0; j < 64; j++) { - - if (j < 16) w[j] = m[j + i]; - else { - - var gamma0x = w[j - 15], - gamma1x = w[j - 2], - gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ - ((gamma0x << 14) | (gamma0x >>> 18)) ^ - (gamma0x >>> 3), - gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ - ((gamma1x << 13) | (gamma1x >>> 19)) ^ - (gamma1x >>> 10); - - w[j] = gamma0 + (w[j - 7] >>> 0) + - gamma1 + (w[j - 16] >>> 0); - - } - - var ch = e & f ^ ~e & g, - maj = a & b ^ a & c ^ b & c, - sigma0 = ((a << 30) | (a >>> 2)) ^ - ((a << 19) | (a >>> 13)) ^ - ((a << 10) | (a >>> 22)), - sigma1 = ((e << 26) | (e >>> 6)) ^ - ((e << 21) | (e >>> 11)) ^ - ((e << 7) | (e >>> 25)); - - - t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0); - t2 = sigma0 + maj; - - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - - } - - H[0] += a; - H[1] += b; - H[2] += c; - H[3] += d; - H[4] += e; - H[5] += f; - H[6] += g; - H[7] += h; - - } - - return H; - -}; - -// Package private blocksize -SHA256._blocksize = 16; - -})(); diff --git a/www/js/BitcoinJS/ecdsa.js b/www/js/BitcoinJS/ecdsa.js deleted file mode 100644 index a2497bf..0000000 --- a/www/js/BitcoinJS/ecdsa.js +++ /dev/null @@ -1,475 +0,0 @@ -function integerToBytes(i, len) { - var bytes = i.toByteArrayUnsigned(); - - if (len < bytes.length) { - bytes = bytes.slice(bytes.length-len); - } else while (len > bytes.length) { - bytes.unshift(0); - } - - return bytes; -}; - -ECFieldElementFp.prototype.getByteLength = function () { - return Math.floor((this.toBigInteger().bitLength() + 7) / 8); -}; - -ECPointFp.prototype.getEncoded = function (compressed) { - var x = this.getX().toBigInteger(); - var y = this.getY().toBigInteger(); - - // Get value as a 32-byte Buffer - // Fixed length based on a patch by bitaddress.org and Casascius - var enc = integerToBytes(x, 32); - - if (compressed) { - if (y.isEven()) { - // Compressed even pubkey - // M = 02 || X - enc.unshift(0x02); - } else { - // Compressed uneven pubkey - // M = 03 || X - enc.unshift(0x03); - } - } else { - // Uncompressed pubkey - // M = 04 || X || Y - enc.unshift(0x04); - enc = enc.concat(integerToBytes(y, 32)); - } - return enc; -}; - -ECPointFp.decodeFrom = function (curve, enc) { - var type = enc[0]; - var dataLen = enc.length-1; - - // Extract x and y as byte arrays - var xBa = enc.slice(1, 1 + dataLen/2); - var yBa = enc.slice(1 + dataLen/2, 1 + dataLen); - - // Prepend zero byte to prevent interpretation as negative integer - xBa.unshift(0); - yBa.unshift(0); - - // Convert to BigIntegers - var x = new BigInteger(xBa); - var y = new BigInteger(yBa); - - // Return point - return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y)); -}; - -ECPointFp.prototype.add2D = function (b) { - if(this.isInfinity()) return b; - if(b.isInfinity()) return this; - - if (this.x.equals(b.x)) { - if (this.y.equals(b.y)) { - // this = b, i.e. this must be doubled - return this.twice(); - } - // this = -b, i.e. the result is the point at infinity - return this.curve.getInfinity(); - } - - var x_x = b.x.subtract(this.x); - var y_y = b.y.subtract(this.y); - var gamma = y_y.divide(x_x); - - var x3 = gamma.square().subtract(this.x).subtract(b.x); - var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); - - return new ECPointFp(this.curve, x3, y3); -}; - -ECPointFp.prototype.twice2D = function () { - if (this.isInfinity()) return this; - if (this.y.toBigInteger().signum() == 0) { - // if y1 == 0, then (x1, y1) == (x1, -y1) - // and hence this = -this and thus 2(x1, y1) == infinity - return this.curve.getInfinity(); - } - - var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); - var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); - var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO)); - - var x3 = gamma.square().subtract(this.x.multiply(TWO)); - var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); - - return new ECPointFp(this.curve, x3, y3); -}; - -ECPointFp.prototype.multiply2D = function (k) { - if(this.isInfinity()) return this; - if(k.signum() == 0) return this.curve.getInfinity(); - - var e = k; - var h = e.multiply(new BigInteger("3")); - - var neg = this.negate(); - var R = this; - - var i; - for (i = h.bitLength() - 2; i > 0; --i) { - R = R.twice(); - - var hBit = h.testBit(i); - var eBit = e.testBit(i); - - if (hBit != eBit) { - R = R.add2D(hBit ? this : neg); - } - } - - return R; -}; - -ECPointFp.prototype.isOnCurve = function () { - var x = this.getX().toBigInteger(); - var y = this.getY().toBigInteger(); - var a = this.curve.getA().toBigInteger(); - var b = this.curve.getB().toBigInteger(); - var n = this.curve.getQ(); - var lhs = y.multiply(y).mod(n); - var rhs = x.multiply(x).multiply(x) - .add(a.multiply(x)).add(b).mod(n); - return lhs.equals(rhs); -}; - -ECPointFp.prototype.toString = function () { - return '('+this.getX().toBigInteger().toString()+','+ - this.getY().toBigInteger().toString()+')'; -}; - -/** - * Validate an elliptic curve point. - * - * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive - */ -ECPointFp.prototype.validate = function () { - var n = this.curve.getQ(); - - // Check Q != O - if (this.isInfinity()) { - throw new Error("Point is at infinity."); - } - - // Check coordinate bounds - var x = this.getX().toBigInteger(); - var y = this.getY().toBigInteger(); - if (x.compareTo(BigInteger.ONE) < 0 || - x.compareTo(n.subtract(BigInteger.ONE)) > 0) { - throw new Error('x coordinate out of bounds'); - } - if (y.compareTo(BigInteger.ONE) < 0 || - y.compareTo(n.subtract(BigInteger.ONE)) > 0) { - throw new Error('y coordinate out of bounds'); - } - - // Check y^2 = x^3 + ax + b (mod n) - if (!this.isOnCurve()) { - throw new Error("Point is not on the curve."); - } - - // Check nQ = 0 (Q is a scalar multiple of G) - if (this.multiply(n).isInfinity()) { - // TODO: This check doesn't work - fix. - throw new Error("Point is not a scalar multiple of G."); - } - - return true; -}; - -function dmp(v) { - if (!(v instanceof BigInteger)) v = v.toBigInteger(); - return Crypto.util.bytesToHex(v.toByteArrayUnsigned()); -}; - -Bitcoin.ECDSA = (function () { - var ecparams = getSECCurveByName("secp256k1"); - var rng = new SecureRandom(); - - var P_OVER_FOUR = null; - - function implShamirsTrick(P, k, Q, l) - { - var m = Math.max(k.bitLength(), l.bitLength()); - var Z = P.add2D(Q); - var R = P.curve.getInfinity(); - - for (var i = m - 1; i >= 0; --i) { - R = R.twice2D(); - - R.z = BigInteger.ONE; - - if (k.testBit(i)) { - if (l.testBit(i)) { - R = R.add2D(Z); - } else { - R = R.add2D(P); - } - } else { - if (l.testBit(i)) { - R = R.add2D(Q); - } - } - } - - return R; - }; - - var ECDSA = { - getBigRandom: function (limit) { - return new BigInteger(limit.bitLength(), rng) - .mod(limit.subtract(BigInteger.ONE)) - .add(BigInteger.ONE) - ; - }, - sign: function (hash, priv) { - var d = priv; - var n = ecparams.getN(); - var e = BigInteger.fromByteArrayUnsigned(hash); - - do { - var k = ECDSA.getBigRandom(n); - var G = ecparams.getG(); - var Q = G.multiply(k); - var r = Q.getX().toBigInteger().mod(n); - } while (r.compareTo(BigInteger.ZERO) <= 0); - - var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); - - return ECDSA.serializeSig(r, s); - }, - - verify: function (hash, sig, pubkey) { - var r,s; - if (Bitcoin.Util.isArray(sig)) { - var obj = ECDSA.parseSig(sig); - r = obj.r; - s = obj.s; - } else if ("object" === typeof sig && sig.r && sig.s) { - r = sig.r; - s = sig.s; - } else { - throw "Invalid value for signature"; - } - - var Q; - if (pubkey instanceof ECPointFp) { - Q = pubkey; - } else if (Bitcoin.Util.isArray(pubkey)) { - Q = ECPointFp.decodeFrom(ecparams.getCurve(), pubkey); - } else { - throw "Invalid format for pubkey value, must be byte array or ECPointFp"; - } - var e = BigInteger.fromByteArrayUnsigned(hash); - - return ECDSA.verifyRaw(e, r, s, Q); - }, - - verifyRaw: function (e, r, s, Q) { - var n = ecparams.getN(); - var G = ecparams.getG(); - - if (r.compareTo(BigInteger.ONE) < 0 || - r.compareTo(n) >= 0) - return false; - - if (s.compareTo(BigInteger.ONE) < 0 || - s.compareTo(n) >= 0) - return false; - - var c = s.modInverse(n); - - var u1 = e.multiply(c).mod(n); - var u2 = r.multiply(c).mod(n); - - // TODO(!!!): For some reason Shamir's trick isn't working with - // signed message verification!? Probably an implementation - // error! - //var point = implShamirsTrick(G, u1, Q, u2); - var point = G.multiply(u1).add(Q.multiply(u2)); - - var v = point.getX().toBigInteger().mod(n); - - return v.equals(r); - }, - - /** - * Serialize a signature into DER format. - * - * Takes two BigIntegers representing r and s and returns a byte array. - */ - serializeSig: function (r, s) { - var rBa = r.toByteArraySigned(); - var sBa = s.toByteArraySigned(); - - var sequence = []; - sequence.push(0x02); // INTEGER - sequence.push(rBa.length); - sequence = sequence.concat(rBa); - - sequence.push(0x02); // INTEGER - sequence.push(sBa.length); - sequence = sequence.concat(sBa); - - sequence.unshift(sequence.length); - sequence.unshift(0x30); // SEQUENCE - - return sequence; - }, - - /** - * Parses a byte array containing a DER-encoded signature. - * - * This function will return an object of the form: - * - * { - * r: BigInteger, - * s: BigInteger - * } - */ - parseSig: function (sig) { - var cursor; - if (sig[0] != 0x30) - throw new Error("Signature not a valid DERSequence"); - - cursor = 2; - if (sig[cursor] != 0x02) - throw new Error("First element in signature must be a DERInteger");; - var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]); - - cursor += 2+sig[cursor+1]; - if (sig[cursor] != 0x02) - throw new Error("Second element in signature must be a DERInteger"); - var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]); - - cursor += 2+sig[cursor+1]; - - //if (cursor != sig.length) - // throw new Error("Extra bytes in signature"); - - var r = BigInteger.fromByteArrayUnsigned(rBa); - var s = BigInteger.fromByteArrayUnsigned(sBa); - - return {r: r, s: s}; - }, - - parseSigCompact: function (sig) { - if (sig.length !== 65) { - throw "Signature has the wrong length"; - } - - // Signature is prefixed with a type byte storing three bits of - // information. - var i = sig[0] - 27; - if (i < 0 || i > 7) { - throw "Invalid signature type"; - } - - var n = ecparams.getN(); - var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n); - var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n); - - return {r: r, s: s, i: i}; - }, - - /** - * Recover a public key from a signature. - * - * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public - * Key Recovery Operation". - * - * http://www.secg.org/download/aid-780/sec1-v2.pdf - */ - recoverPubKey: function (r, s, hash, i) { - // The recovery parameter i has two bits. - i = i & 3; - - // The less significant bit specifies whether the y coordinate - // of the compressed point is even or not. - var isYEven = i & 1; - - // The more significant bit specifies whether we should use the - // first or second candidate key. - var isSecondKey = i >> 1; - - var n = ecparams.getN(); - var G = ecparams.getG(); - var curve = ecparams.getCurve(); - var p = curve.getQ(); - var a = curve.getA().toBigInteger(); - var b = curve.getB().toBigInteger(); - - // We precalculate (p + 1) / 4 where p is if the field order - if (!P_OVER_FOUR) { - P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4)); - } - - // 1.1 Compute x - var x = isSecondKey ? r.add(n) : r; - - // 1.3 Convert x to point - var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p); - var beta = alpha.modPow(P_OVER_FOUR, p); - - var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2); - // If beta is even, but y isn't or vice versa, then convert it, - // otherwise we're done and y == beta. - var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta); - - // 1.4 Check that nR is at infinity - var R = new ECPointFp(curve, - curve.fromBigInteger(x), - curve.fromBigInteger(y)); - R.validate(); - - // 1.5 Compute e from M - var e = BigInteger.fromByteArrayUnsigned(hash); - var eNeg = BigInteger.ZERO.subtract(e).mod(n); - - // 1.6 Compute Q = r^-1 (sR - eG) - var rInv = r.modInverse(n); - var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv); - - Q.validate(); - if (!ECDSA.verifyRaw(e, r, s, Q)) { - throw "Pubkey recovery unsuccessful"; - } - - var pubKey = new Bitcoin.ECKey(); - pubKey.pub = Q; - return pubKey; - }, - - /** - * Calculate pubkey extraction parameter. - * - * When extracting a pubkey from a signature, we have to - * distinguish four different cases. Rather than putting this - * burden on the verifier, Bitcoin includes a 2-bit value with the - * signature. - * - * This function simply tries all four cases and returns the value - * that resulted in a successful pubkey recovery. - */ - calcPubkeyRecoveryParam: function (address, r, s, hash) - { - for (var i = 0; i < 4; i++) { - try { - var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i); - if (pubkey.getBitcoinAddress().toString() == address) { - return i; - } - } catch (e) {} - } - throw "Unable to find valid recovery factor"; - } - }; - - return ECDSA; -})(); diff --git a/www/js/BitcoinJS/eckey.js b/www/js/BitcoinJS/eckey.js deleted file mode 100644 index a01367b..0000000 --- a/www/js/BitcoinJS/eckey.js +++ /dev/null @@ -1,131 +0,0 @@ -Bitcoin.ECKey = (function () { - var ECDSA = Bitcoin.ECDSA; - var ecparams = getSECCurveByName("secp256k1"); - var rng = new SecureRandom(); - - var ECKey = function (input) { - if (!input) { - // Generate new key - var n = ecparams.getN(); - this.priv = ECDSA.getBigRandom(n); - } else if (input instanceof BigInteger) { - // Input is a private key value - this.priv = input; - } else if (Bitcoin.Util.isArray(input)) { - // Prepend zero byte to prevent interpretation as negative integer - this.priv = BigInteger.fromByteArrayUnsigned(input); - } else if ("string" == typeof input) { - if (input.length == 51 && input[0] == '5') { - // Base58 encoded private key - this.priv = BigInteger.fromByteArrayUnsigned(ECKey.decodeString(input)); - } else { - // Prepend zero byte to prevent interpretation as negative integer - this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input)); - } - } - this.compressed = !!ECKey.compressByDefault; - }; - - /** - * Whether public keys should be returned compressed by default. - */ - ECKey.compressByDefault = false; - - /** - * Set whether the public key should be returned compressed or not. - */ - ECKey.prototype.setCompressed = function (v) { - this.compressed = !!v; - }; - - /** - * Return public key in DER encoding. - */ - ECKey.prototype.getPub = function () { - return this.getPubPoint().getEncoded(this.compressed); - }; - - /** - * Return public point as ECPoint object. - */ - ECKey.prototype.getPubPoint = function () { - if (!this.pub) this.pub = ecparams.getG().multiply(this.priv); - - return this.pub; - }; - - /** - * Get the pubKeyHash for this key. - * - * This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as - * a byte array. - */ - ECKey.prototype.getPubKeyHash = function () { - if (this.pubKeyHash) return this.pubKeyHash; - - return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub()); - }; - - ECKey.prototype.getBitcoinAddress = function () { - var hash = this.getPubKeyHash(); - var addr = new Bitcoin.Address(hash); - return addr; - }; - - ECKey.prototype.getExportedPrivateKey = function () { - var hash = this.priv.toByteArrayUnsigned(); - while (hash.length < 32) hash.unshift(0); - hash.unshift(0x80); - var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); - var bytes = hash.concat(checksum.slice(0,4)); - return Bitcoin.Base58.encode(bytes); - }; - - ECKey.prototype.setPub = function (pub) { - this.pub = ECPointFp.decodeFrom(ecparams.getCurve(), pub); - }; - - ECKey.prototype.toString = function (format) { - if (format === "base64") { - return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned()); - } else { - return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned()); - } - }; - - ECKey.prototype.sign = function (hash) { - return ECDSA.sign(hash, this.priv); - }; - - ECKey.prototype.verify = function (hash, sig) { - return ECDSA.verify(hash, sig, this.getPub()); - }; - - /** - * Parse an exported private key contained in a string. - */ - ECKey.decodeString = function (string) { - var bytes = Bitcoin.Base58.decode(string); - - var hash = bytes.slice(0, 33); - - var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); - - if (checksum[0] != bytes[33] || - checksum[1] != bytes[34] || - checksum[2] != bytes[35] || - checksum[3] != bytes[36]) { - throw "Checksum validation failed!"; - } - - var version = hash.shift(); - - if (version != 0x80) { - throw "Version "+version+" not supported!"; - } - - return hash; - }; - - return ECKey; -})(); diff --git a/www/js/BitcoinJS/events/eventemitter.js b/www/js/BitcoinJS/events/eventemitter.js deleted file mode 100644 index 85d9dce..0000000 --- a/www/js/BitcoinJS/events/eventemitter.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * EventEmitter Mixin - * - * Designed to be used in conjunction with a mixin "augment" function, - * such as http://chamnapchhorn.blogspot.com/2009/05/javascript-mixins.html - * - * @usage augment(MyClass, EventEmitter); - * my_inst = new MyClass(); - * my_inst.on('someEvent', function(e){ console.dir(e); }); - * my_inst.trigger('someEvent', {eventProp:'value'}); - * - * @example - * // create a 'class' - * MyClass = function() {} - * // augment it with EventEmitter - * EventEmitter.augment(MyClass.prototype); - * // create a method, which triggers an event - * MyClass.prototype.scrollComplete = function() { - * this.trigger('scrolled', {baz:'eck'}); - * }; - * - * // this callback is pulled out into a named function so that we can unbind it - * var callback = function(e) { - * console.log('the scrolled event was fired! this.foo='+this.foo+', e.baz='+e.baz); - * }; - * // create an instance of th class - * var myinstance = new MyClass(); - * // set a property on the instance - * myinstance.foo = 'bar'; - * // bind to the scrollComplete event - * myinstance.on('scrolled', callback, myinstance); - * // fire the method, which should trigger the event and therefore our callback - * myinstance.scrollComplete(); - * // unbind the event, so that our callback should not get called - * myinstance.removeListener('scrolled', callback); - * // this should now not fire the callback - * myinstance.scrollComplete(); - */ -var EventEmitter = function() {}; -/** - * Bind a callback to an event, with an option scope context - * - * @param {string} name the name of the event - * @param {function} callback the callback function to fire when the event is triggered - * @param {object} context the scope to use for the callback (which will become 'this' inside the callback) - */ -EventEmitter.prototype.on = function(name, callback, context) { - if (!context) context = this; - if (!this._listeners) this._listeners = {}; - if (!this._listeners[name]) this._listeners[name] = []; - if (!this._unbinders) this._unbinders = {}; - if (!this._unbinders[name]) this._unbinders[name] = []; - var f = function(e) { - callback.apply(context, [e]); - }; - this._unbinders[name].push(callback); - this._listeners[name].push(f); -}; -/** - * Trigger an event, firing all bound callbacks - * - * @param {string} name the name of the event - * @param {object} event the event object to be passed through to the callback - */ -EventEmitter.prototype.trigger = function(name, event) { - if (event === undefined) event = {} - if (!this._listeners) this._listeners = {}; - if (!this._listeners[name]) return; - var i = this._listeners[name].length; - while (i--) this._listeners[name][i](event); -}; -/** - * Remove a bound listener - * - * @param {string} name the name of the event - * @param {object} event the event object to be passed through to the callback - */ -EventEmitter.prototype.removeListener = function(name, callback) { - if (!this._unbinders) this._unbinders = {}; - if (!this._unbinders[name]) return; - var i = this._unbinders[name].length; - while (i--) { - if (this._unbinders[name][i] === callback) { - this._unbinders[name].splice(i, 1); - this._listeners[name].splice(i, 1); - } - } -}; -/** - * Augment an object with the EventEmitter mixin - * - * @param {object} obj The object to be augmented (often an object's protoype) - */ -EventEmitter.augment = function(obj) { - for (var method in EventEmitter.prototype) { - if (!obj[method]) obj[method] = EventEmitter.prototype[method]; - } -}; diff --git a/www/js/BitcoinJS/exit/client.js b/www/js/BitcoinJS/exit/client.js deleted file mode 100644 index 86d9f55..0000000 --- a/www/js/BitcoinJS/exit/client.js +++ /dev/null @@ -1,148 +0,0 @@ -(function (exports, Bitcoin, io, $, global) { - - /** - * Expose constructor. - */ - - exports.ExitNode = ExitNode; - - function ExitNode(host, port, secure) { - this.setUri(host, port, secure); - - this.unique = 1; - this.connected = false; - - this.callbacks = []; - }; - - Bitcoin.EventEmitter.augment(ExitNode); - - ExitNode.prototype.setUri = function (host, port, secure) { - this.uri = (secure ? "https://" : "http://")+host+":"+port; - }; - - ExitNode.prototype.connect = function (wallet) { - this.wallet = wallet; - - // Workaround for socket.io not properly allowing disconnecting and reconnecting - delete io.sockets[this.uri]; - io.j = []; - - this.socket = io.connect(this.uri); - this.socket.on('connect', $.proxy(this.handleConnect, this)); - this.socket.on('error', function () { - console.log('error, test'); - }); - this.socket.on('message', $.proxy(this.handleMessage, this)); - this.socket.on('disconnect', $.proxy(this.handleDisconnect, this)); - }; - - ExitNode.prototype.disconnect = function () { - if (this.socket) { - this.socket.disconnect(); - this.socket = null; - this.connected = false; - } - - this.trigger('connectStatus', {status: 'unknown'}); - }; - - /** - * Make RPC call. - */ - ExitNode.prototype.call = function (method, argObj, callback) { - this.socket.send($.toJSON({ - "method": method, - "params": [argObj], - "id": this.unique - })); - if (callback) this.callbacks[this.unique] = callback; - this.unique++; - }; - - ExitNode.prototype.handleConnect = function () { - var self = this; - - this.connected = true; - }; - - ExitNode.prototype.listen = function (addrs) { - self.call("pubkeysRegister", { - keys: addrs.join(',') - }, function (err, result) { - if (err) { - console.error("Could not register public keys"); - return; - } - - self.call("pubkeysListen", { - handle: result.handle - }, function (err, result) { - // Communicate the block height - self.trigger('blockInit', {height: result.height}); - - // Pass on the newly downloaded transactions - self.trigger('txData', { - confirmed: true, - txs: result.txs - }); - - // TODO: Download more transactions - - self.trigger('connectStatus', {status: 'ok'}); - }); - - self.call("pubkeysUnconfirmed", { - handle: result.handle - }, function (err, result) { - // Pass on the newly downloaded transactions - self.trigger('txData', { - confirmed: false, - txs: result.txs - }); - }); - }); - }; - - - ExitNode.prototype.handleMessage = function (data) { - // Handle JSON-RPC result messages - if ("undefined" !== typeof data.result && - "function" == typeof this.callbacks[data.id]) { - this.callbacks[data.id](data.error, data.result); - - // Handle JSON-RPC request messages - } else if ("undefined" !== typeof data.method) { - // Create an event - this.trigger(data.method, data.params[0]); - } - }; - - - ExitNode.prototype.handleDisconnect = function () { - // TODO: Attempt reconnect (unless disconnect was intended) - }; - - ExitNode.prototype.query = function (api, params, jsonp, callback) { - if ("function" === typeof jsonp) { - callback = jsonp; - jsonp = false; - } - - params = params || {}; - callback = "function" === typeof callback ? callback : function () {}; - - var url = this.uri + '/' + api; - if (jsonp) { - url += "?callback=?"; - } - - $.getJSON(url, params, callback); - }; -})( - 'undefined' != typeof Bitcoin ? Bitcoin : module.exports, - 'undefined' != typeof Bitcoin ? Bitcoin : require('bitcoinjs-lib'), - 'undefined' != typeof io ? io : require('io'), - jQuery, // TODO: Add Node.js equivalent - this -); diff --git a/www/js/BitcoinJS/jsbn/ec.js b/www/js/BitcoinJS/jsbn/ec.js deleted file mode 100644 index 43ded3e..0000000 --- a/www/js/BitcoinJS/jsbn/ec.js +++ /dev/null @@ -1,316 +0,0 @@ -// Basic Javascript Elliptic Curve implementation -// Ported loosely from BouncyCastle's Java EC code -// Only Fp curves implemented for now - -// Requires jsbn.js and jsbn2.js - -// ---------------- -// ECFieldElementFp - -// constructor -function ECFieldElementFp(q,x) { - this.x = x; - // TODO if(x.compareTo(q) >= 0) error - this.q = q; -} - -function feFpEquals(other) { - if(other == this) return true; - return (this.q.equals(other.q) && this.x.equals(other.x)); -} - -function feFpToBigInteger() { - return this.x; -} - -function feFpNegate() { - return new ECFieldElementFp(this.q, this.x.negate().mod(this.q)); -} - -function feFpAdd(b) { - return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q)); -} - -function feFpSubtract(b) { - return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q)); -} - -function feFpMultiply(b) { - return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q)); -} - -function feFpSquare() { - return new ECFieldElementFp(this.q, this.x.square().mod(this.q)); -} - -function feFpDivide(b) { - return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q)); -} - -ECFieldElementFp.prototype.equals = feFpEquals; -ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger; -ECFieldElementFp.prototype.negate = feFpNegate; -ECFieldElementFp.prototype.add = feFpAdd; -ECFieldElementFp.prototype.subtract = feFpSubtract; -ECFieldElementFp.prototype.multiply = feFpMultiply; -ECFieldElementFp.prototype.square = feFpSquare; -ECFieldElementFp.prototype.divide = feFpDivide; - -// ---------------- -// ECPointFp - -// constructor -function ECPointFp(curve,x,y,z) { - this.curve = curve; - this.x = x; - this.y = y; - // Projective coordinates: either zinv == null or z * zinv == 1 - // z and zinv are just BigIntegers, not fieldElements - if(z == null) { - this.z = BigInteger.ONE; - } - else { - this.z = z; - } - this.zinv = null; - //TODO: compression flag -} - -function pointFpGetX() { - if(this.zinv == null) { - this.zinv = this.z.modInverse(this.curve.q); - } - return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)); -} - -function pointFpGetY() { - if(this.zinv == null) { - this.zinv = this.z.modInverse(this.curve.q); - } - return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)); -} - -function pointFpEquals(other) { - if(other == this) return true; - if(this.isInfinity()) return other.isInfinity(); - if(other.isInfinity()) return this.isInfinity(); - var u, v; - // u = Y2 * Z1 - Y1 * Z2 - u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q); - if(!u.equals(BigInteger.ZERO)) return false; - // v = X2 * Z1 - X1 * Z2 - v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q); - return v.equals(BigInteger.ZERO); -} - -function pointFpIsInfinity() { - if((this.x == null) && (this.y == null)) return true; - return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO); -} - -function pointFpNegate() { - return new ECPointFp(this.curve, this.x, this.y.negate(), this.z); -} - -function pointFpAdd(b) { - if(this.isInfinity()) return b; - if(b.isInfinity()) return this; - - // u = Y2 * Z1 - Y1 * Z2 - var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q); - // v = X2 * Z1 - X1 * Z2 - var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q); - - if(BigInteger.ZERO.equals(v)) { - if(BigInteger.ZERO.equals(u)) { - return this.twice(); // this == b, so double - } - return this.curve.getInfinity(); // this = -b, so infinity - } - - var THREE = new BigInteger("3"); - var x1 = this.x.toBigInteger(); - var y1 = this.y.toBigInteger(); - var x2 = b.x.toBigInteger(); - var y2 = b.y.toBigInteger(); - - var v2 = v.square(); - var v3 = v2.multiply(v); - var x1v2 = x1.multiply(v2); - var zu2 = u.square().multiply(this.z); - - // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) - var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q); - // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 - var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q); - // z3 = v^3 * z1 * z2 - var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q); - - return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); -} - -function pointFpTwice() { - if(this.isInfinity()) return this; - if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity(); - - // TODO: optimized handling of constants - var THREE = new BigInteger("3"); - var x1 = this.x.toBigInteger(); - var y1 = this.y.toBigInteger(); - - var y1z1 = y1.multiply(this.z); - var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q); - var a = this.curve.a.toBigInteger(); - - // w = 3 * x1^2 + a * z1^2 - var w = x1.square().multiply(THREE); - if(!BigInteger.ZERO.equals(a)) { - w = w.add(this.z.square().multiply(a)); - } - w = w.mod(this.curve.q); - // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) - var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q); - // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 - var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q); - // z3 = 8 * (y1 * z1)^3 - var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q); - - return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); -} - -// Simple NAF (Non-Adjacent Form) multiplication algorithm -// TODO: modularize the multiplication algorithm -function pointFpMultiply(k) { - if(this.isInfinity()) return this; - if(k.signum() == 0) return this.curve.getInfinity(); - - var e = k; - var h = e.multiply(new BigInteger("3")); - - var neg = this.negate(); - var R = this; - - var i; - for(i = h.bitLength() - 2; i > 0; --i) { - R = R.twice(); - - var hBit = h.testBit(i); - var eBit = e.testBit(i); - - if (hBit != eBit) { - R = R.add(hBit ? this : neg); - } - } - - return R; -} - -// Compute this*j + x*k (simultaneous multiplication) -function pointFpMultiplyTwo(j,x,k) { - var i; - if(j.bitLength() > k.bitLength()) - i = j.bitLength() - 1; - else - i = k.bitLength() - 1; - - var R = this.curve.getInfinity(); - var both = this.add(x); - while(i >= 0) { - R = R.twice(); - if(j.testBit(i)) { - if(k.testBit(i)) { - R = R.add(both); - } - else { - R = R.add(this); - } - } - else { - if(k.testBit(i)) { - R = R.add(x); - } - } - --i; - } - - return R; -} - -ECPointFp.prototype.getX = pointFpGetX; -ECPointFp.prototype.getY = pointFpGetY; -ECPointFp.prototype.equals = pointFpEquals; -ECPointFp.prototype.isInfinity = pointFpIsInfinity; -ECPointFp.prototype.negate = pointFpNegate; -ECPointFp.prototype.add = pointFpAdd; -ECPointFp.prototype.twice = pointFpTwice; -ECPointFp.prototype.multiply = pointFpMultiply; -ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo; - -// ---------------- -// ECCurveFp - -// constructor -function ECCurveFp(q,a,b) { - this.q = q; - this.a = this.fromBigInteger(a); - this.b = this.fromBigInteger(b); - this.infinity = new ECPointFp(this, null, null); -} - -function curveFpGetQ() { - return this.q; -} - -function curveFpGetA() { - return this.a; -} - -function curveFpGetB() { - return this.b; -} - -function curveFpEquals(other) { - if(other == this) return true; - return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)); -} - -function curveFpGetInfinity() { - return this.infinity; -} - -function curveFpFromBigInteger(x) { - return new ECFieldElementFp(this.q, x); -} - -// for now, work with hex strings because they're easier in JS -function curveFpDecodePointHex(s) { - switch(parseInt(s.substr(0,2), 16)) { // first byte - case 0: - return this.infinity; - case 2: - case 3: - // point compression not supported yet - return null; - case 4: - case 6: - case 7: - var len = (s.length - 2) / 2; - var xHex = s.substr(2, len); - var yHex = s.substr(len+2, len); - - return new ECPointFp(this, - this.fromBigInteger(new BigInteger(xHex, 16)), - this.fromBigInteger(new BigInteger(yHex, 16))); - - default: // unsupported - return null; - } -} - -ECCurveFp.prototype.getQ = curveFpGetQ; -ECCurveFp.prototype.getA = curveFpGetA; -ECCurveFp.prototype.getB = curveFpGetB; -ECCurveFp.prototype.equals = curveFpEquals; -ECCurveFp.prototype.getInfinity = curveFpGetInfinity; -ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger; -ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex; diff --git a/www/js/BitcoinJS/jsbn/jsbn.js b/www/js/BitcoinJS/jsbn/jsbn.js deleted file mode 100644 index 40bb9e2..0000000 --- a/www/js/BitcoinJS/jsbn/jsbn.js +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) 2005 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Basic JavaScript BN library - subset useful for RSA encryption. - -// Bits per digit -var dbits; - -// JavaScript engine analysis -var canary = 0xdeadbeefcafe; -var j_lm = ((canary&0xffffff)==0xefcafe); - -// (public) Constructor -function BigInteger(a,b,c) { - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); -} - -// return new, unset BigInteger -function nbi() { return new BigInteger(null); } - -// am: Compute w_j += (x*this_i), propagate carries, -// c is initial carry, returns final carry. -// c < 3*dvalue, x < 2*dvalue, this_i < dvalue -// We need to select the fastest one that works in this environment. - -// am1: use a single mult and divide to get the high bits, -// max digit bits should be 26 because -// max internal value = 2*dvalue^2-2*dvalue (< 2^53) -function am1(i,x,w,j,c,n) { - while(--n >= 0) { - var v = x*this[i++]+w[j]+c; - c = Math.floor(v/0x4000000); - w[j++] = v&0x3ffffff; - } - return c; -} -// am2 avoids a big mult-and-extract completely. -// Max digit bits should be <= 30 because we do bitwise ops -// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) -function am2(i,x,w,j,c,n) { - var xl = x&0x7fff, xh = x>>15; - while(--n >= 0) { - var l = this[i]&0x7fff; - var h = this[i++]>>15; - var m = xh*l+h*xl; - l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); - c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); - w[j++] = l&0x3fffffff; - } - return c; -} -// Alternately, set max digit bits to 28 since some -// browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this[i]&0x3fff; - var h = this[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w[j++] = l&0xfffffff; - } - return c; -} -if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { - BigInteger.prototype.am = am2; - dbits = 30; -} -else if(j_lm && (navigator.appName != "Netscape")) { - BigInteger.prototype.am = am1; - dbits = 26; -} -else { // Mozilla/Netscape seems to prefer am3 - BigInteger.prototype.am = am3; - dbits = 28; -} - -BigInteger.prototype.DB = dbits; -BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; - r.t = this.t; - r.s = this.s; -} - -// (protected) set from integer value x, -DV <= x < DV -function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this[0] = x; - else if(x < -1) this[0] = x+DV; - else this.t = 0; -} - -// return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } - -// (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this[this.t++] = x; - else if(sh+k > this.DB) { - this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); - } - else - this[this.t-1] |= x<= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; -} - -// (public) return string representation in given radix -function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1< 0) { - if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this[i]&((1<>(p+=this.DB-k); - } - else { - d = (this[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; -} - -// (public) -this -function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } - -// (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } - -// (public) return + if this > a, - if this < a, 0 if equal -function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return (this.s<0)?-r:r; - while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; - return 0; -} - -// returns bit length of the integer x -function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; -} - -// (public) return the number of bits in "this" -function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); -} - -// (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; - for(i = n-1; i >= 0; --i) r[i] = 0; - r.t = this.t+n; - r.s = this.s; -} - -// (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r[i-n] = this[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; -} - -// (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<= 0; --i) { - r[i+ds+1] = (this[i]>>cbs)|c; - c = (this[i]&bm)<= 0; --i) r[i] = 0; - r[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); -} - -// (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<>bs; - for(var i = ds+1; i < this.t; ++i) { - r[i-ds-1] |= (this[i]&bm)<>bs; - } - if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c -= a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r[i++] = this.DV+c; - else if(c > 0) r[i++] = c; - r.t = i; - r.clamp(); -} - -// (protected) r = this * a, r != this,a (HAC 14.12) -// "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger.ZERO.subTo(r,r); -} - -// (protected) r = this^2, r != this (HAC 14.16) -function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x[i],r,2*i,0,1); - if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r[i+x.t] -= x.DV; - r[i+x.t+1] = 1; - } - } - if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); - r.s = 0; - r.clamp(); -} - -// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) -// r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } - else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<1)?y[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<= 0) { - r[r.t++] = 1; - r.subTo(t,r); - } - BigInteger.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); - if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger.ZERO.subTo(r,r); -} - -// (public) this mod a -function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); - return r; -} - -// Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } -function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; -} -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -Classic.prototype.convert = cConvert; -Classic.prototype.revert = cRevert; -Classic.prototype.reduce = cReduce; -Classic.prototype.mulTo = cMulTo; -Classic.prototype.sqrTo = cSqrTo; - -// (protected) return "-1/this % 2^DB"; useful for Mont. reduction -// justification: -// xy == 1 (mod m) -// xy = 1+km -// xy(2-xy) = (1+km)(1-km) -// x[y(2-xy)] = 1-k^2m^2 -// x[y(2-xy)] == 1 (mod m^2) -// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 -// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. -// JS multiply "overflows" differently from C/C++, so care is needed here. -function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; -} - -// Montgomery reduction -function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; -} - -// xR mod m -function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); - return r; -} - -// x/R mod m -function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; -} - -// x = x/R mod m (HAC 14.32) -function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x[i]*mp mod DV - var j = x[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Montgomery.prototype.convert = montConvert; -Montgomery.prototype.revert = montRevert; -Montgomery.prototype.reduce = montReduce; -Montgomery.prototype.mulTo = montMulTo; -Montgomery.prototype.sqrTo = montSqrTo; - -// (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } - -// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1< 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); -} - -// (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); -} - -// protected -BigInteger.prototype.copyTo = bnpCopyTo; -BigInteger.prototype.fromInt = bnpFromInt; -BigInteger.prototype.fromString = bnpFromString; -BigInteger.prototype.clamp = bnpClamp; -BigInteger.prototype.dlShiftTo = bnpDLShiftTo; -BigInteger.prototype.drShiftTo = bnpDRShiftTo; -BigInteger.prototype.lShiftTo = bnpLShiftTo; -BigInteger.prototype.rShiftTo = bnpRShiftTo; -BigInteger.prototype.subTo = bnpSubTo; -BigInteger.prototype.multiplyTo = bnpMultiplyTo; -BigInteger.prototype.squareTo = bnpSquareTo; -BigInteger.prototype.divRemTo = bnpDivRemTo; -BigInteger.prototype.invDigit = bnpInvDigit; -BigInteger.prototype.isEven = bnpIsEven; -BigInteger.prototype.exp = bnpExp; - -// public -BigInteger.prototype.toString = bnToString; -BigInteger.prototype.negate = bnNegate; -BigInteger.prototype.abs = bnAbs; -BigInteger.prototype.compareTo = bnCompareTo; -BigInteger.prototype.bitLength = bnBitLength; -BigInteger.prototype.mod = bnMod; -BigInteger.prototype.modPowInt = bnModPowInt; - -// "constants" -BigInteger.ZERO = nbv(0); -BigInteger.ONE = nbv(1); diff --git a/www/js/BitcoinJS/jsbn/jsbn2.js b/www/js/BitcoinJS/jsbn/jsbn2.js deleted file mode 100644 index 5b2b725..0000000 --- a/www/js/BitcoinJS/jsbn/jsbn2.js +++ /dev/null @@ -1,656 +0,0 @@ -// Copyright (c) 2005-2009 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Extended JavaScript BN functions, required for RSA private ops. - -// Version 1.1: new BigInteger("0", 10) returns "proper" zero -// Version 1.2: square() API, isProbablePrime fix - -// (public) -function bnClone() { var r = nbi(); this.copyTo(r); return r; } - -// (public) return value as integer -function bnIntValue() { - if(this.s < 0) { - if(this.t == 1) return this[0]-this.DV; - else if(this.t == 0) return -1; - } - else if(this.t == 1) return this[0]; - else if(this.t == 0) return 0; - // assumes 16 < DB < 32 - return ((this[1]&((1<<(32-this.DB))-1))<>24; } - -// (public) return value as short (assumes DB>=16) -function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } - -// (protected) return x s.t. r^x < DV -function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } - -// (public) 0 if this == 0, 1 if this > 0 -function bnSigNum() { - if(this.s < 0) return -1; - else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; - else return 1; -} - -// (protected) convert to radix string -function bnpToRadix(b) { - if(b == null) b = 10; - if(this.signum() == 0 || b < 2 || b > 36) return "0"; - var cs = this.chunkSize(b); - var a = Math.pow(b,cs); - var d = nbv(a), y = nbi(), z = nbi(), r = ""; - this.divRemTo(d,y,z); - while(y.signum() > 0) { - r = (a+z.intValue()).toString(b).substr(1) + r; - y.divRemTo(d,y,z); - } - return z.intValue().toString(b) + r; -} - -// (protected) convert from radix string -function bnpFromRadix(s,b) { - this.fromInt(0); - if(b == null) b = 10; - var cs = this.chunkSize(b); - var d = Math.pow(b,cs), mi = false, j = 0, w = 0; - for(var i = 0; i < s.length; ++i) { - var x = intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-" && this.signum() == 0) mi = true; - continue; - } - w = b*w+x; - if(++j >= cs) { - this.dMultiply(d); - this.dAddOffset(w,0); - j = 0; - w = 0; - } - } - if(j > 0) { - this.dMultiply(Math.pow(b,j)); - this.dAddOffset(w,0); - } - if(mi) BigInteger.ZERO.subTo(this,this); -} - -// (protected) alternate constructor -function bnpFromNumber(a,b,c) { - if("number" == typeof b) { - // new BigInteger(int,int,RNG) - if(a < 2) this.fromInt(1); - else { - this.fromNumber(a,c); - if(!this.testBit(a-1)) // force MSB set - this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); - if(this.isEven()) this.dAddOffset(1,0); // force odd - while(!this.isProbablePrime(b)) { - this.dAddOffset(2,0); - if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); - } - } - } - else { - // new BigInteger(int,RNG) - var x = new Array(), t = a&7; - x.length = (a>>3)+1; - b.nextBytes(x); - if(t > 0) x[0] &= ((1< 0) { - if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) - r[k++] = d|(this.s<<(this.DB-p)); - while(i >= 0) { - if(p < 8) { - d = (this[i]&((1<>(p+=this.DB-8); - } - else { - d = (this[i]>>(p-=8))&0xff; - if(p <= 0) { p += this.DB; --i; } - } - if((d&0x80) != 0) d |= -256; - if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; - if(k > 0 || d != this.s) r[k++] = d; - } - } - return r; -} - -function bnEquals(a) { return(this.compareTo(a)==0); } -function bnMin(a) { return(this.compareTo(a)<0)?this:a; } -function bnMax(a) { return(this.compareTo(a)>0)?this:a; } - -// (protected) r = this op a (bitwise) -function bnpBitwiseTo(a,op,r) { - var i, f, m = Math.min(a.t,this.t); - for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); - if(a.t < this.t) { - f = a.s&this.DM; - for(i = m; i < this.t; ++i) r[i] = op(this[i],f); - r.t = this.t; - } - else { - f = this.s&this.DM; - for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); - r.t = a.t; - } - r.s = op(this.s,a.s); - r.clamp(); -} - -// (public) this & a -function op_and(x,y) { return x&y; } -function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } - -// (public) this | a -function op_or(x,y) { return x|y; } -function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } - -// (public) this ^ a -function op_xor(x,y) { return x^y; } -function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } - -// (public) this & ~a -function op_andnot(x,y) { return x&~y; } -function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } - -// (public) ~this -function bnNot() { - var r = nbi(); - for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; - r.t = this.t; - r.s = ~this.s; - return r; -} - -// (public) this << n -function bnShiftLeft(n) { - var r = nbi(); - if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); - return r; -} - -// (public) this >> n -function bnShiftRight(n) { - var r = nbi(); - if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); - return r; -} - -// return index of lowest 1-bit in x, x < 2^31 -function lbit(x) { - if(x == 0) return -1; - var r = 0; - if((x&0xffff) == 0) { x >>= 16; r += 16; } - if((x&0xff) == 0) { x >>= 8; r += 8; } - if((x&0xf) == 0) { x >>= 4; r += 4; } - if((x&3) == 0) { x >>= 2; r += 2; } - if((x&1) == 0) ++r; - return r; -} - -// (public) returns index of lowest 1-bit (or -1 if none) -function bnGetLowestSetBit() { - for(var i = 0; i < this.t; ++i) - if(this[i] != 0) return i*this.DB+lbit(this[i]); - if(this.s < 0) return this.t*this.DB; - return -1; -} - -// return number of 1 bits in x -function cbit(x) { - var r = 0; - while(x != 0) { x &= x-1; ++r; } - return r; -} - -// (public) return number of set bits -function bnBitCount() { - var r = 0, x = this.s&this.DM; - for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); - return r; -} - -// (public) true iff nth bit is set -function bnTestBit(n) { - var j = Math.floor(n/this.DB); - if(j >= this.t) return(this.s!=0); - return((this[j]&(1<<(n%this.DB)))!=0); -} - -// (protected) this op (1<>= this.DB; - } - if(a.t < this.t) { - c += a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c += a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += a.s; - } - r.s = (c<0)?-1:0; - if(c > 0) r[i++] = c; - else if(c < -1) r[i++] = this.DV+c; - r.t = i; - r.clamp(); -} - -// (public) this + a -function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } - -// (public) this - a -function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } - -// (public) this * a -function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } - -// (public) this^2 -function bnSquare() { var r = nbi(); this.squareTo(r); return r; } - -// (public) this / a -function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } - -// (public) this % a -function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } - -// (public) [this/a,this%a] -function bnDivideAndRemainder(a) { - var q = nbi(), r = nbi(); - this.divRemTo(a,q,r); - return new Array(q,r); -} - -// (protected) this *= n, this >= 0, 1 < n < DV -function bnpDMultiply(n) { - this[this.t] = this.am(0,n-1,this,0,0,this.t); - ++this.t; - this.clamp(); -} - -// (protected) this += n << w words, this >= 0 -function bnpDAddOffset(n,w) { - if(n == 0) return; - while(this.t <= w) this[this.t++] = 0; - this[w] += n; - while(this[w] >= this.DV) { - this[w] -= this.DV; - if(++w >= this.t) this[this.t++] = 0; - ++this[w]; - } -} - -// A "null" reducer -function NullExp() {} -function nNop(x) { return x; } -function nMulTo(x,y,r) { x.multiplyTo(y,r); } -function nSqrTo(x,r) { x.squareTo(r); } - -NullExp.prototype.convert = nNop; -NullExp.prototype.revert = nNop; -NullExp.prototype.mulTo = nMulTo; -NullExp.prototype.sqrTo = nSqrTo; - -// (public) this^e -function bnPow(e) { return this.exp(e,new NullExp()); } - -// (protected) r = lower n words of "this * a", a.t <= n -// "this" should be the larger one if appropriate. -function bnpMultiplyLowerTo(a,n,r) { - var i = Math.min(this.t+a.t,n); - r.s = 0; // assumes a,this >= 0 - r.t = i; - while(i > 0) r[--i] = 0; - var j; - for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); - for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); - r.clamp(); -} - -// (protected) r = "this * a" without lower n words, n > 0 -// "this" should be the larger one if appropriate. -function bnpMultiplyUpperTo(a,n,r) { - --n; - var i = r.t = this.t+a.t-n; - r.s = 0; // assumes a,this >= 0 - while(--i >= 0) r[i] = 0; - for(i = Math.max(n-this.t,0); i < a.t; ++i) - r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); - r.clamp(); - r.drShiftTo(1,r); -} - -// Barrett modular reduction -function Barrett(m) { - // setup Barrett - this.r2 = nbi(); - this.q3 = nbi(); - BigInteger.ONE.dlShiftTo(2*m.t,this.r2); - this.mu = this.r2.divide(m); - this.m = m; -} - -function barrettConvert(x) { - if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); - else if(x.compareTo(this.m) < 0) return x; - else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } -} - -function barrettRevert(x) { return x; } - -// x = x mod m (HAC 14.42) -function barrettReduce(x) { - x.drShiftTo(this.m.t-1,this.r2); - if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } - this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); - this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); - while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); - x.subTo(this.r2,x); - while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = x^2 mod m; x != r -function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = x*y mod m; x,y != r -function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Barrett.prototype.convert = barrettConvert; -Barrett.prototype.revert = barrettRevert; -Barrett.prototype.reduce = barrettReduce; -Barrett.prototype.mulTo = barrettMulTo; -Barrett.prototype.sqrTo = barrettSqrTo; - -// (public) this^e % m (HAC 14.85) -function bnModPow(e,m) { - var i = e.bitLength(), k, r = nbv(1), z; - if(i <= 0) return r; - else if(i < 18) k = 1; - else if(i < 48) k = 3; - else if(i < 144) k = 4; - else if(i < 768) k = 5; - else k = 6; - if(i < 8) - z = new Classic(m); - else if(m.isEven()) - z = new Barrett(m); - else - z = new Montgomery(m); - - // precomputation - var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { - var g2 = nbi(); - z.sqrTo(g[1],g2); - while(n <= km) { - g[n] = nbi(); - z.mulTo(g2,g[n-2],g[n]); - n += 2; - } - } - - var j = e.t-1, w, is1 = true, r2 = nbi(), t; - i = nbits(e[j])-1; - while(j >= 0) { - if(i >= k1) w = (e[j]>>(i-k1))&km; - else { - w = (e[j]&((1<<(i+1))-1))<<(k1-i); - if(j > 0) w |= e[j-1]>>(this.DB+i-k1); - } - - n = k; - while((w&1) == 0) { w >>= 1; --n; } - if((i -= n) < 0) { i += this.DB; --j; } - if(is1) { // ret == 1, don't bother squaring or multiplying it - g[w].copyTo(r); - is1 = false; - } - else { - while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } - if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } - z.mulTo(r2,g[w],r); - } - - while(j >= 0 && (e[j]&(1< 0) { - x.rShiftTo(g,x); - y.rShiftTo(g,y); - } - while(x.signum() > 0) { - if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); - if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); - if(x.compareTo(y) >= 0) { - x.subTo(y,x); - x.rShiftTo(1,x); - } - else { - y.subTo(x,y); - y.rShiftTo(1,y); - } - } - if(g > 0) y.lShiftTo(g,y); - return y; -} - -// (protected) this % n, n < 2^26 -function bnpModInt(n) { - if(n <= 0) return 0; - var d = this.DV%n, r = (this.s<0)?n-1:0; - if(this.t > 0) - if(d == 0) r = this[0]%n; - else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; - return r; -} - -// (public) 1/this % m (HAC 14.61) -function bnModInverse(m) { - var ac = m.isEven(); - if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; - var u = m.clone(), v = this.clone(); - var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); - while(u.signum() != 0) { - while(u.isEven()) { - u.rShiftTo(1,u); - if(ac) { - if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } - a.rShiftTo(1,a); - } - else if(!b.isEven()) b.subTo(m,b); - b.rShiftTo(1,b); - } - while(v.isEven()) { - v.rShiftTo(1,v); - if(ac) { - if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } - c.rShiftTo(1,c); - } - else if(!d.isEven()) d.subTo(m,d); - d.rShiftTo(1,d); - } - if(u.compareTo(v) >= 0) { - u.subTo(v,u); - if(ac) a.subTo(c,a); - b.subTo(d,b); - } - else { - v.subTo(u,v); - if(ac) c.subTo(a,c); - d.subTo(b,d); - } - } - if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; - if(d.compareTo(m) >= 0) return d.subtract(m); - if(d.signum() < 0) d.addTo(m,d); else return d; - if(d.signum() < 0) return d.add(m); else return d; -} - -var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; -var lplim = (1<<26)/lowprimes[lowprimes.length-1]; - -// (public) test primality with certainty >= 1-.5^t -function bnIsProbablePrime(t) { - var i, x = this.abs(); - if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { - for(i = 0; i < lowprimes.length; ++i) - if(x[0] == lowprimes[i]) return true; - return false; - } - if(x.isEven()) return false; - i = 1; - while(i < lowprimes.length) { - var m = lowprimes[i], j = i+1; - while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; - m = x.modInt(m); - while(i < j) if(m%lowprimes[i++] == 0) return false; - } - return x.millerRabin(t); -} - -// (protected) true if probably prime (HAC 4.24, Miller-Rabin) -function bnpMillerRabin(t) { - var n1 = this.subtract(BigInteger.ONE); - var k = n1.getLowestSetBit(); - if(k <= 0) return false; - var r = n1.shiftRight(k); - t = (t+1)>>1; - if(t > lowprimes.length) t = lowprimes.length; - var a = nbi(); - for(var i = 0; i < t; ++i) { - //Pick bases at random, instead of starting at 2 - a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); - var y = a.modPow(r,this); - if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { - var j = 1; - while(j++ < k && y.compareTo(n1) != 0) { - y = y.modPowInt(2,this); - if(y.compareTo(BigInteger.ONE) == 0) return false; - } - if(y.compareTo(n1) != 0) return false; - } - } - return true; -} - -// protected -BigInteger.prototype.chunkSize = bnpChunkSize; -BigInteger.prototype.toRadix = bnpToRadix; -BigInteger.prototype.fromRadix = bnpFromRadix; -BigInteger.prototype.fromNumber = bnpFromNumber; -BigInteger.prototype.bitwiseTo = bnpBitwiseTo; -BigInteger.prototype.changeBit = bnpChangeBit; -BigInteger.prototype.addTo = bnpAddTo; -BigInteger.prototype.dMultiply = bnpDMultiply; -BigInteger.prototype.dAddOffset = bnpDAddOffset; -BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; -BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; -BigInteger.prototype.modInt = bnpModInt; -BigInteger.prototype.millerRabin = bnpMillerRabin; - -// public -BigInteger.prototype.clone = bnClone; -BigInteger.prototype.intValue = bnIntValue; -BigInteger.prototype.byteValue = bnByteValue; -BigInteger.prototype.shortValue = bnShortValue; -BigInteger.prototype.signum = bnSigNum; -BigInteger.prototype.toByteArray = bnToByteArray; -BigInteger.prototype.equals = bnEquals; -BigInteger.prototype.min = bnMin; -BigInteger.prototype.max = bnMax; -BigInteger.prototype.and = bnAnd; -BigInteger.prototype.or = bnOr; -BigInteger.prototype.xor = bnXor; -BigInteger.prototype.andNot = bnAndNot; -BigInteger.prototype.not = bnNot; -BigInteger.prototype.shiftLeft = bnShiftLeft; -BigInteger.prototype.shiftRight = bnShiftRight; -BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; -BigInteger.prototype.bitCount = bnBitCount; -BigInteger.prototype.testBit = bnTestBit; -BigInteger.prototype.setBit = bnSetBit; -BigInteger.prototype.clearBit = bnClearBit; -BigInteger.prototype.flipBit = bnFlipBit; -BigInteger.prototype.add = bnAdd; -BigInteger.prototype.subtract = bnSubtract; -BigInteger.prototype.multiply = bnMultiply; -BigInteger.prototype.divide = bnDivide; -BigInteger.prototype.remainder = bnRemainder; -BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; -BigInteger.prototype.modPow = bnModPow; -BigInteger.prototype.modInverse = bnModInverse; -BigInteger.prototype.pow = bnPow; -BigInteger.prototype.gcd = bnGCD; -BigInteger.prototype.isProbablePrime = bnIsProbablePrime; - -// JSBN-specific extension -BigInteger.prototype.square = bnSquare; - -// BigInteger interfaces not implemented in jsbn: - -// BigInteger(int signum, byte[] magnitude) -// double doubleValue() -// float floatValue() -// int hashCode() -// long longValue() -// static BigInteger valueOf(long val) diff --git a/www/js/BitcoinJS/jsbn/prng4.js b/www/js/BitcoinJS/jsbn/prng4.js deleted file mode 100644 index 3034f3f..0000000 --- a/www/js/BitcoinJS/jsbn/prng4.js +++ /dev/null @@ -1,45 +0,0 @@ -// prng4.js - uses Arcfour as a PRNG - -function Arcfour() { - this.i = 0; - this.j = 0; - this.S = new Array(); -} - -// Initialize arcfour context from key, an array of ints, each from [0..255] -function ARC4init(key) { - var i, j, t; - for(i = 0; i < 256; ++i) - this.S[i] = i; - j = 0; - for(i = 0; i < 256; ++i) { - j = (j + this.S[i] + key[i % key.length]) & 255; - t = this.S[i]; - this.S[i] = this.S[j]; - this.S[j] = t; - } - this.i = 0; - this.j = 0; -} - -function ARC4next() { - var t; - this.i = (this.i + 1) & 255; - this.j = (this.j + this.S[this.i]) & 255; - t = this.S[this.i]; - this.S[this.i] = this.S[this.j]; - this.S[this.j] = t; - return this.S[(t + this.S[this.i]) & 255]; -} - -Arcfour.prototype.init = ARC4init; -Arcfour.prototype.next = ARC4next; - -// Plug in your RNG constructor here -function prng_newstate() { - return new Arcfour(); -} - -// Pool size must be a multiple of 4 and greater than 32. -// An array of bytes the size of the pool will be passed to init() -var rng_psize = 256; diff --git a/www/js/BitcoinJS/jsbn/rng.js b/www/js/BitcoinJS/jsbn/rng.js deleted file mode 100644 index 03afc3a..0000000 --- a/www/js/BitcoinJS/jsbn/rng.js +++ /dev/null @@ -1,68 +0,0 @@ -// Random number generator - requires a PRNG backend, e.g. prng4.js - -// For best results, put code like -// -// in your main HTML document. - -var rng_state; -var rng_pool; -var rng_pptr; - -// Mix in a 32-bit integer into the pool -function rng_seed_int(x) { - rng_pool[rng_pptr++] ^= x & 255; - rng_pool[rng_pptr++] ^= (x >> 8) & 255; - rng_pool[rng_pptr++] ^= (x >> 16) & 255; - rng_pool[rng_pptr++] ^= (x >> 24) & 255; - if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; -} - -// Mix in the current time (w/milliseconds) into the pool -function rng_seed_time() { - rng_seed_int(new Date().getTime()); -} - -// Initialize the pool with junk if needed. -if(rng_pool == null) { - rng_pool = new Array(); - rng_pptr = 0; - var t; - if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { - // Extract entropy (256 bits) from NS4 RNG if available - var z = window.crypto.random(32); - for(t = 0; t < z.length; ++t) - rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; - } - while(rng_pptr < rng_psize) { // extract some randomness from Math.random() - t = Math.floor(65536 * Math.random()); - rng_pool[rng_pptr++] = t >>> 8; - rng_pool[rng_pptr++] = t & 255; - } - rng_pptr = 0; - rng_seed_time(); - //rng_seed_int(window.screenX); - //rng_seed_int(window.screenY); -} - -function rng_get_byte() { - if(rng_state == null) { - rng_seed_time(); - rng_state = prng_newstate(); - rng_state.init(rng_pool); - for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) - rng_pool[rng_pptr] = 0; - rng_pptr = 0; - //rng_pool = null; - } - // TODO: allow reseeding after first request - return rng_state.next(); -} - -function rng_get_bytes(ba) { - var i; - for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); -} - -function SecureRandom() {} - -SecureRandom.prototype.nextBytes = rng_get_bytes; diff --git a/www/js/BitcoinJS/jsbn/sec.js b/www/js/BitcoinJS/jsbn/sec.js deleted file mode 100644 index e496571..0000000 --- a/www/js/BitcoinJS/jsbn/sec.js +++ /dev/null @@ -1,173 +0,0 @@ -// Named EC curves - -// Requires ec.js, jsbn.js, and jsbn2.js - -// ---------------- -// X9ECParameters - -// constructor -function X9ECParameters(curve,g,n,h) { - this.curve = curve; - this.g = g; - this.n = n; - this.h = h; -} - -function x9getCurve() { - return this.curve; -} - -function x9getG() { - return this.g; -} - -function x9getN() { - return this.n; -} - -function x9getH() { - return this.h; -} - -X9ECParameters.prototype.getCurve = x9getCurve; -X9ECParameters.prototype.getG = x9getG; -X9ECParameters.prototype.getN = x9getN; -X9ECParameters.prototype.getH = x9getH; - -// ---------------- -// SECNamedCurves - -function fromHex(s) { return new BigInteger(s, 16); } - -function secp128r1() { - // p = 2^128 - 2^97 - 1 - var p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); - var a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"); - var b = fromHex("E87579C11079F43DD824993C2CEE5ED3"); - //byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679"); - var n = fromHex("FFFFFFFE0000000075A30D1B9038A115"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "161FF7528B899B2D0C28607CA52C5B86" - + "CF5AC8395BAFEB13C02DA292DDED7A83"); - return new X9ECParameters(curve, G, n, h); -} - -function secp160k1() { - // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); - var a = BigInteger.ZERO; - var b = fromHex("7"); - //byte[] S = null; - var n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" - + "938CF935318FDCED6BC28286531733C3F03C4FEE"); - return new X9ECParameters(curve, G, n, h); -} - -function secp160r1() { - // p = 2^160 - 2^31 - 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"); - var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"); - var b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"); - //byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345"); - var n = fromHex("0100000000000000000001F4C8F927AED3CA752257"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "4A96B5688EF573284664698968C38BB913CBFC82" - + "23A628553168947D59DCC912042351377AC5FB32"); - return new X9ECParameters(curve, G, n, h); -} - -function secp192k1() { - // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"); - var a = BigInteger.ZERO; - var b = fromHex("3"); - //byte[] S = null; - var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" - + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"); - return new X9ECParameters(curve, G, n, h); -} - -function secp192r1() { - // p = 2^192 - 2^64 - 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); - var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); - var b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); - //byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); - var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" - + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"); - return new X9ECParameters(curve, G, n, h); -} - -function secp224r1() { - // p = 2^224 - 2^96 + 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); - var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"); - var b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"); - //byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); - var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" - + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"); - return new X9ECParameters(curve, G, n, h); -} - -function secp256k1() { - // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 - var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); - var a = BigInteger.ZERO; - var b = fromHex("7"); - //byte[] S = null; - var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" - + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); - return new X9ECParameters(curve, G, n, h); -} - -function secp256r1() { - // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 - var p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); - var a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); - var b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); - //byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); - var n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); - var h = BigInteger.ONE; - var curve = new ECCurveFp(p, a, b); - var G = curve.decodePointHex("04" - + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" - + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"); - return new X9ECParameters(curve, G, n, h); -} - -// TODO: make this into a proper hashtable -function getSECCurveByName(name) { - if(name == "secp128r1") return secp128r1(); - if(name == "secp160k1") return secp160k1(); - if(name == "secp160r1") return secp160r1(); - if(name == "secp192k1") return secp192k1(); - if(name == "secp192r1") return secp192r1(); - if(name == "secp224r1") return secp224r1(); - if(name == "secp256k1") return secp256k1(); - if(name == "secp256r1") return secp256r1(); - return null; -} diff --git a/www/js/BitcoinJS/message.js b/www/js/BitcoinJS/message.js deleted file mode 100644 index a2dabc0..0000000 --- a/www/js/BitcoinJS/message.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Implements Bitcoin's feature for signing arbitrary messages. - */ -Bitcoin.Message = (function () { - var Message = {}; - - Message.magicPrefix = "Bitcoin Signed Message:\n"; - - Message.makeMagicMessage = function (message) { - var magicBytes = Crypto.charenc.UTF8.stringToBytes(Message.magicPrefix); - var messageBytes = Crypto.charenc.UTF8.stringToBytes(message); - - var buffer = []; - buffer = buffer.concat(Bitcoin.Util.numToVarInt(magicBytes.length)); - buffer = buffer.concat(magicBytes); - buffer = buffer.concat(Bitcoin.Util.numToVarInt(messageBytes.length)); - buffer = buffer.concat(messageBytes); - - return buffer; - }; - - Message.getHash = function (message) { - var buffer = Message.makeMagicMessage(message); - return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); - }; - - Message.signMessage = function (key, message, compressed) { - var hash = Message.getHash(message); - - var sig = key.sign(hash); - - var obj = Bitcoin.ECDSA.parseSig(sig); - - var address = key.getBitcoinAddress().toString(); - var i = Bitcoin.ECDSA.calcPubkeyRecoveryParam(address, obj.r, obj.s, hash); - - i += 27; - if (compressed) i += 4; - - var rBa = obj.r.toByteArrayUnsigned(); - var sBa = obj.s.toByteArrayUnsigned(); - - // Pad to 32 bytes per value - while (rBa.length < 32) rBa.unshift(0); - while (sBa.length < 32) sBa.unshift(0); - - sig = [i].concat(rBa).concat(sBa); - - return Crypto.util.bytesToBase64(sig); - }; - - Message.verifyMessage = function (address, sig, message) { - sig = Crypto.util.base64ToBytes(sig); - sig = Bitcoin.ECDSA.parseSigCompact(sig); - - var hash = Message.getHash(message); - - var isCompressed = !!(sig.i & 4); - var pubKey = Bitcoin.ECDSA.recoverPubKey(sig.r, sig.s, hash, sig.i); - - pubKey.setCompressed(isCompressed); - - var expectedAddress = pubKey.getBitcoinAddress().toString(); - - return (address === expectedAddress); - }; - - return Message; -})(); diff --git a/www/js/BitcoinJS/opcode.js b/www/js/BitcoinJS/opcode.js deleted file mode 100644 index b21da46..0000000 --- a/www/js/BitcoinJS/opcode.js +++ /dev/null @@ -1,154 +0,0 @@ -(function () { - var Opcode = Bitcoin.Opcode = function (num) { - this.code = num; - }; - - Opcode.prototype.toString = function () { - return Opcode.reverseMap[this.code]; - }; - - Opcode.map = { - // push value - OP_0 : 0, - OP_FALSE : 0, - OP_PUSHDATA1 : 76, - OP_PUSHDATA2 : 77, - OP_PUSHDATA4 : 78, - OP_1NEGATE : 79, - OP_RESERVED : 80, - OP_1 : 81, - OP_TRUE : 81, - OP_2 : 82, - OP_3 : 83, - OP_4 : 84, - OP_5 : 85, - OP_6 : 86, - OP_7 : 87, - OP_8 : 88, - OP_9 : 89, - OP_10 : 90, - OP_11 : 91, - OP_12 : 92, - OP_13 : 93, - OP_14 : 94, - OP_15 : 95, - OP_16 : 96, - - // control - OP_NOP : 97, - OP_VER : 98, - OP_IF : 99, - OP_NOTIF : 100, - OP_VERIF : 101, - OP_VERNOTIF : 102, - OP_ELSE : 103, - OP_ENDIF : 104, - OP_VERIFY : 105, - OP_RETURN : 106, - - // stack ops - OP_TOALTSTACK : 107, - OP_FROMALTSTACK : 108, - OP_2DROP : 109, - OP_2DUP : 110, - OP_3DUP : 111, - OP_2OVER : 112, - OP_2ROT : 113, - OP_2SWAP : 114, - OP_IFDUP : 115, - OP_DEPTH : 116, - OP_DROP : 117, - OP_DUP : 118, - OP_NIP : 119, - OP_OVER : 120, - OP_PICK : 121, - OP_ROLL : 122, - OP_ROT : 123, - OP_SWAP : 124, - OP_TUCK : 125, - - // splice ops - OP_CAT : 126, - OP_SUBSTR : 127, - OP_LEFT : 128, - OP_RIGHT : 129, - OP_SIZE : 130, - - // bit logic - OP_INVERT : 131, - OP_AND : 132, - OP_OR : 133, - OP_XOR : 134, - OP_EQUAL : 135, - OP_EQUALVERIFY : 136, - OP_RESERVED1 : 137, - OP_RESERVED2 : 138, - - // numeric - OP_1ADD : 139, - OP_1SUB : 140, - OP_2MUL : 141, - OP_2DIV : 142, - OP_NEGATE : 143, - OP_ABS : 144, - OP_NOT : 145, - OP_0NOTEQUAL : 146, - - OP_ADD : 147, - OP_SUB : 148, - OP_MUL : 149, - OP_DIV : 150, - OP_MOD : 151, - OP_LSHIFT : 152, - OP_RSHIFT : 153, - - OP_BOOLAND : 154, - OP_BOOLOR : 155, - OP_NUMEQUAL : 156, - OP_NUMEQUALVERIFY : 157, - OP_NUMNOTEQUAL : 158, - OP_LESSTHAN : 159, - OP_GREATERTHAN : 160, - OP_LESSTHANOREQUAL : 161, - OP_GREATERTHANOREQUAL : 162, - OP_MIN : 163, - OP_MAX : 164, - - OP_WITHIN : 165, - - // crypto - OP_RIPEMD160 : 166, - OP_SHA1 : 167, - OP_SHA256 : 168, - OP_HASH160 : 169, - OP_HASH256 : 170, - OP_CODESEPARATOR : 171, - OP_CHECKSIG : 172, - OP_CHECKSIGVERIFY : 173, - OP_CHECKMULTISIG : 174, - OP_CHECKMULTISIGVERIFY : 175, - - // expansion - OP_NOP1 : 176, - OP_NOP2 : 177, - OP_NOP3 : 178, - OP_NOP4 : 179, - OP_NOP5 : 180, - OP_NOP6 : 181, - OP_NOP7 : 182, - OP_NOP8 : 183, - OP_NOP9 : 184, - OP_NOP10 : 185, - - // template matching params - OP_PUBKEYHASH : 253, - OP_PUBKEY : 254, - OP_INVALIDOPCODE : 255 - }; - - Opcode.reverseMap = []; - - for (var i in Opcode.map) { - Opcode.reverseMap[Opcode.map[i]] = i; - } -})(); diff --git a/www/js/BitcoinJS/paillier.js b/www/js/BitcoinJS/paillier.js deleted file mode 100644 index 54881ba..0000000 --- a/www/js/BitcoinJS/paillier.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Implement the Paillier cryptosystem in JavaScript. - * - * Paillier is useful for multiparty calculation. It is not currently part of any - * BitcoinJS-lib distribution, but it is included here for experimental use. - */ -Bitcoin.Paillier = (function () { - var rng = new SecureRandom(); - var TWO = BigInteger.valueOf(2); - - var Paillier = { - generate: function (bitLength) { - var p, q; - do { - p = new BigInteger(bitLength, 1, rng); - q = new BigInteger(bitLength, 1, rng); - } while (p.equals(q)); - - var n = p.multiply(q); - - // p - 1 - var p1 = p.subtract(BigInteger.ONE); - // q - 1 - var q1 = q.subtract(BigInteger.ONE); - - var nSq = n.multiply(n); - - // lambda - var l = p1.multiply(q1).divide(p1.gcd(q1)); - - var coprimeBitLength = n.bitLength() - Math.floor(Math.random()*10); - - var alpha = new BigInteger(coprimeBitLength, 1, rng); - var beta = new BigInteger(coprimeBitLength, 1, rng); - - var g = alpha.multiply(n).add(BigInteger.ONE) - .multiply(beta.modPow(n,nSq)).mod(nSq); - - // mu - var m = g.modPow(l,nSq).mod(nSq) - .subtract(BigInteger.ONE).divide(n).modInverse(n); - - return new Paillier.PrivateKey(n,g,l,m,nSq); - } - }; - - Paillier.PublicKey = function (n,g,nSq) { - this.n = n; - this.g = g; - this.nSq = nSq || n.multiply(n); - }; - - Paillier.PublicKey.prototype.encrypt = function (i, r) { - if (!r) { - var coprimeBitLength = this.n.bitLength() - Math.floor(Math.random()*10); - r = new BigInteger(coprimeBitLength, 1, rng); - } - return this.g.modPow(i,this.nSq).multiply(r.modPow(this.n,this.nSq)) - .mod(this.nSq); - }; - - Paillier.PublicKey.prototype.add = function (c, f) { - return c.multiply(this.encrypt(f)).mod(this.nSq); - }; - - Paillier.PublicKey.prototype.addCrypt = function (c, f) { - return c.multiply(f).mod(this.nSq); - }; - - Paillier.PublicKey.prototype.multiply = function (c, f) { - return c.modPow(f, this.nSq); - }; - - Paillier.PublicKey.prototype.rerandomize = function (c, r) { - if (!r) { - var coprimeBitLength = this.n.bitLength() - Math.floor(Math.random()*10); - r = new BigInteger(coprimeBitLength, 1, rng); - } - return c.multiply(r.modPow(this.n, this.nSq)).mod(this.nSq); - }; - - Paillier.PrivateKey = function (n,g,l,m,nSq) { - this.l = l; - this.m = m; - this.n = n; - this.nSq = nSq || n.multiply(n); - this.pub = new Paillier.PublicKey(n,g,this.nSq); - }; - - Paillier.PrivateKey.prototype.decrypt = function (c) { - return c.modPow(this.l, this.nSq).subtract(BigInteger.ONE) - .divide(this.n).multiply(this.m).mod(this.n); - }; - - Paillier.PrivateKey.prototype.decryptR = function (c, i) { - if (!i) { - i = this.decrypt(c); - } - var rn = c.multiply(this.pub.g.modPow(i, this.nSq).modInverse(this.nSq)) - .mod(this.nSq); - var a = this.l.modInverse(this.n).multiply(this.n.subtract(BigInteger.ONE)); - var e = a.multiply(this.l).add(BigInteger.ONE).divide(this.n); - return rn.modPow(e, this.n); - }; - - function createProxyMethod(name) { - return function () { - return this.pub[name].apply(this.pub, - Array.prototype.slice.apply(arguments)); - }; - }; - var a = ["add", "addCrypt", "multiply", "rerandomize", "encrypt"]; - for (var i = 0, l = a.length; i < l; i++) { - Paillier.PrivateKey.prototype[a[i]] = createProxyMethod(a[i]); - } - - return Paillier; -})(); diff --git a/www/js/BitcoinJS/script.js b/www/js/BitcoinJS/script.js deleted file mode 100644 index 71f1ef5..0000000 --- a/www/js/BitcoinJS/script.js +++ /dev/null @@ -1,347 +0,0 @@ -(function () { - var Opcode = Bitcoin.Opcode; - - // Make opcodes available as pseudo-constants - for (var i in Opcode.map) { - eval("var " + i + " = " + Opcode.map[i] + ";"); - } - - var Script = Bitcoin.Script = function (data) { - if (!data) { - this.buffer = []; - } else if ("string" == typeof data) { - this.buffer = Crypto.util.base64ToBytes(data); - } else if (Bitcoin.Util.isArray(data)) { - this.buffer = data; - } else if (data instanceof Script) { - this.buffer = data.buffer; - } else { - throw new Error("Invalid script"); - } - - this.parse(); - }; - - /** - * Update the parsed script representation. - * - * Each Script object stores the script in two formats. First as a raw byte - * array and second as an array of "chunks", such as opcodes and pieces of - * data. - * - * This method updates the chunks cache. Normally this is called by the - * constructor and you don't need to worry about it. However, if you change - * the script buffer manually, you should update the chunks using this method. - */ - Script.prototype.parse = function () { - var self = this; - - this.chunks = []; - - // Cursor - var i = 0; - - // Read n bytes and store result as a chunk - function readChunk(n) { - self.chunks.push(self.buffer.slice(i, i + n)); - i += n; - }; - - while (i < this.buffer.length) { - var opcode = this.buffer[i++]; - if (opcode >= 0xF0) { - // Two byte opcode - opcode = (opcode << 8) | this.buffer[i++]; - } - - var len; - if (opcode > 0 && opcode < OP_PUSHDATA1) { - // Read some bytes of data, opcode value is the length of data - readChunk(opcode); - } else if (opcode == OP_PUSHDATA1) { - len = this.buffer[i++]; - readChunk(len); - } else if (opcode == OP_PUSHDATA2) { - len = (this.buffer[i++] << 8) | this.buffer[i++]; - readChunk(len); - } else if (opcode == OP_PUSHDATA4) { - len = (this.buffer[i++] << 24) | - (this.buffer[i++] << 16) | - (this.buffer[i++] << 8) | - this.buffer[i++]; - readChunk(len); - } else { - this.chunks.push(opcode); - } - } - }; - - /** - * Compare the script to known templates of scriptPubKey. - * - * This method will compare the script to a small number of standard script - * templates and return a string naming the detected type. - * - * Currently supported are: - * Address: - * Paying to a Bitcoin address which is the hash of a pubkey. - * OP_DUP OP_HASH160 [pubKeyHash] OP_EQUALVERIFY OP_CHECKSIG - * - * Pubkey: - * Paying to a public key directly. - * [pubKey] OP_CHECKSIG - * - * Strange: - * Any other script (no template matched). - */ - Script.prototype.getOutType = function () { - - if (this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG && this.chunks[this.chunks.length-2] <= 3) { - // Transfer to M-OF-N - return 'Multisig'; - } else if (this.chunks.length == 5 && - this.chunks[0] == OP_DUP && - this.chunks[1] == OP_HASH160 && - this.chunks[3] == OP_EQUALVERIFY && - this.chunks[4] == OP_CHECKSIG) { - // Transfer to Bitcoin address - return 'Address'; - } else if (this.chunks.length == 2 && - this.chunks[1] == OP_CHECKSIG) { - // Transfer to IP address - return 'Pubkey'; - } else { - return 'Strange'; - } -} - - /** - * Returns the affected address hash for this output. - * - * For standard transactions, this will return the hash of the pubKey that - * can spend this output. - * - * In the future, for payToScriptHash outputs, this will return the - * scriptHash. Note that non-standard and standard payToScriptHash transactions - * look the same - * - * This method is useful for indexing transactions. - */ - Script.prototype.simpleOutHash = function () - { - switch (this.getOutType()) { - case 'Address': - return this.chunks[2]; - case 'Pubkey': - return Bitcoin.Util.sha256ripe160(this.chunks[0]); - default: - throw new Error("Encountered non-standard scriptPubKey"); - } - }; - - /** - * Old name for Script#simpleOutHash. - * - * @deprecated - */ - Script.prototype.simpleOutPubKeyHash = Script.prototype.simpleOutHash; - - /** - * Compare the script to known templates of scriptSig. - * - * This method will compare the script to a small number of standard script - * templates and return a string naming the detected type. - * - * WARNING: Use this method with caution. It merely represents a heuristic - * based on common transaction formats. A non-standard transaction could - * very easily match one of these templates by accident. - * - * Currently supported are: - * Address: - * Paying to a Bitcoin address which is the hash of a pubkey. - * [sig] [pubKey] - * - * Pubkey: - * Paying to a public key directly. - * [sig] - * - * Strange: - * Any other script (no template matched). - */ - Script.prototype.getInType = function () - { - if (this.chunks.length == 1 && - Bitcoin.Util.isArray(this.chunks[0])) { - // Direct IP to IP transactions only have the signature in their scriptSig. - // TODO: We could also check that the length of the data is correct. - return 'Pubkey'; - } else if (this.chunks.length == 2 && - Bitcoin.Util.isArray(this.chunks[0]) && - Bitcoin.Util.isArray(this.chunks[1])) { - return 'Address'; - } else { - return 'Strange'; - } - }; - - /** - * Returns the affected public key for this input. - * - * This currently only works with payToPubKeyHash transactions. It will also - * work in the future for standard payToScriptHash transactions that use a - * single public key. - * - * However for multi-key and other complex transactions, this will only return - * one of the keys or raise an error. Therefore, it is recommended for indexing - * purposes to use Script#simpleInHash or Script#simpleOutHash instead. - * - * @deprecated - */ - Script.prototype.simpleInPubKey = function () - { - switch (this.getInType()) { - case 'Address': - return this.chunks[1]; - case 'Pubkey': - // TODO: Theoretically, we could recover the pubkey from the sig here. - // See https://bitcointalk.org/?topic=6430.0 - throw new Error("Script does not contain pubkey."); - default: - throw new Error("Encountered non-standard scriptSig"); - } - }; - - /** - * Returns the affected address hash for this input. - * - * For standard transactions, this will return the hash of the pubKey that - * can spend this output. - * - * In the future, for standard payToScriptHash inputs, this will return the - * scriptHash. - * - * Note: This function provided for convenience. If you have the corresponding - * scriptPubKey available, you are urged to use Script#simpleOutHash instead - * as it is more reliable for non-standard payToScriptHash transactions. - * - * This method is useful for indexing transactions. - */ - Script.prototype.simpleInHash = function () - { - return Bitcoin.Util.sha256ripe160(this.simpleInPubKey()); - }; - - /** - * Old name for Script#simpleInHash. - * - * @deprecated - */ - Script.prototype.simpleInPubKeyHash = Script.prototype.simpleInHash; - - /** - * Add an op code to the script. - */ - Script.prototype.writeOp = function (opcode) - { - this.buffer.push(opcode); - this.chunks.push(opcode); - }; - - /** - * Add a data chunk to the script. - */ - Script.prototype.writeBytes = function (data) - { - if (data.length < OP_PUSHDATA1) { - this.buffer.push(data.length); - } else if (data.length <= 0xff) { - this.buffer.push(OP_PUSHDATA1); - this.buffer.push(data.length); - } else if (data.length <= 0xffff) { - this.buffer.push(OP_PUSHDATA2); - this.buffer.push(data.length & 0xff); - this.buffer.push((data.length >>> 8) & 0xff); - } else { - this.buffer.push(OP_PUSHDATA4); - this.buffer.push(data.length & 0xff); - this.buffer.push((data.length >>> 8) & 0xff); - this.buffer.push((data.length >>> 16) & 0xff); - this.buffer.push((data.length >>> 24) & 0xff); - } - this.buffer = this.buffer.concat(data); - this.chunks.push(data); - }; - - /** - * Create a standard payToPubKeyHash output. - */ - Script.createOutputScript = function (address) - { - var script = new Script(); - script.writeOp(OP_DUP); - script.writeOp(OP_HASH160); - script.writeBytes(address.hash); - script.writeOp(OP_EQUALVERIFY); - script.writeOp(OP_CHECKSIG); - return script; - }; - - - /** - * Extract bitcoin addresses from an output script - */ - Script.prototype.extractAddresses = function (addresses) - { - switch (this.getOutType()) { - case 'Address': - addresses.push(new Address(this.chunks[2])); - return 1; - case 'Pubkey': - addresses.push(new Address(Util.sha256ripe160(this.chunks[0]))); - return 1; - case 'Multisig': - for (var i = 1; i < this.chunks.length-2; ++i) { - addresses.push(new Address(Util.sha256ripe160(this.chunks[i]))); - } - return this.chunks[0] - OP_1 + 1; - default: - throw new Error("Encountered non-standard scriptPubKey"); - } - }; - - /** - * Create an m-of-n output script - */ - Script.createMultiSigOutputScript = function (m, pubkeys) - { - var script = new Bitcoin.Script(); - - script.writeOp(OP_1 + m - 1); - - for (var i = 0; i < pubkeys.length; ++i) { - script.writeBytes(pubkeys[i]); - } - - script.writeOp(OP_1 + pubkeys.length - 1); - - script.writeOp(OP_CHECKMULTISIG); - - return script; - }; - - /** - * Create a standard payToPubKeyHash input. - */ - Script.createInputScript = function (signature, pubKey) - { - var script = new Script(); - script.writeBytes(signature); - script.writeBytes(pubKey); - return script; - }; - - Script.prototype.clone = function () - { - return new Script(this.buffer); - }; -})(); diff --git a/www/js/BitcoinJS/transaction.js b/www/js/BitcoinJS/transaction.js deleted file mode 100644 index c06dc87..0000000 --- a/www/js/BitcoinJS/transaction.js +++ /dev/null @@ -1,445 +0,0 @@ -(function () { - var Script = Bitcoin.Script; - - var Transaction = Bitcoin.Transaction = function (doc) { - this.version = 1; - this.lock_time = 0; - this.ins = []; - this.outs = []; - this.timestamp = null; - this.block = null; - - if (doc) { - if (doc.hash) this.hash = doc.hash; - if (doc.version) this.version = doc.version; - if (doc.lock_time) this.lock_time = doc.lock_time; - if (doc.ins && doc.ins.length) { - for (var i = 0; i < doc.ins.length; i++) { - this.addInput(new TransactionIn(doc.ins[i])); - } - } - if (doc.outs && doc.outs.length) { - for (var i = 0; i < doc.outs.length; i++) { - this.addOutput(new TransactionOut(doc.outs[i])); - } - } - if (doc.timestamp) this.timestamp = doc.timestamp; - if (doc.block) this.block = doc.block; - } - }; - - /** - * Turn transaction data into Transaction objects. - * - * Takes an array of plain JavaScript objects containing transaction data and - * returns an array of Transaction objects. - */ - Transaction.objectify = function (txs) { - var objs = []; - for (var i = 0; i < txs.length; i++) { - objs.push(new Transaction(txs[i])); - } - return objs; - }; - - /** - * Create a new txin. - * - * Can be called with an existing TransactionIn object to add it to the - * transaction. Or it can be called with a Transaction object and an integer - * output index, in which case a new TransactionIn object pointing to the - * referenced output will be created. - * - * Note that this method does not sign the created input. - */ - Transaction.prototype.addInput = function (tx, outIndex) { - if (arguments[0] instanceof TransactionIn) { - this.ins.push(arguments[0]); - } else { - this.ins.push(new TransactionIn({ - outpoint: { - hash: tx.hash, - index: outIndex - }, - script: new Bitcoin.Script(), - sequence: 4294967295 - })); - } - }; - - /** - * Create a new txout. - * - * Can be called with an existing TransactionOut object to add it to the - * transaction. Or it can be called with an Address object and a BigInteger - * for the amount, in which case a new TransactionOut object with those - * values will be created. - */ - Transaction.prototype.addOutput = function (address, value) { - if (arguments[0] instanceof TransactionOut) { - this.outs.push(arguments[0]); - } else { - if (value instanceof BigInteger) { - value = value.toByteArrayUnsigned().reverse(); - while (value.length < 8) value.push(0); - } else if (Bitcoin.Util.isArray(value)) { - // Nothing to do - } - - this.outs.push(new TransactionOut({ - value: value, - script: Script.createOutputScript(address) - })); - } - }; - - /** - * Serialize this transaction. - * - * Returns the transaction as a byte array in the standard Bitcoin binary - * format. This method is byte-perfect, i.e. the resulting byte array can - * be hashed to get the transaction's standard Bitcoin hash. - */ - Transaction.prototype.serialize = function () - { - var buffer = []; - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(this.version)]).reverse()); - buffer = buffer.concat(Bitcoin.Util.numToVarInt(this.ins.length)); - for (var i = 0; i < this.ins.length; i++) { - var txin = this.ins[i]; - buffer = buffer.concat(Crypto.util.base64ToBytes(txin.outpoint.hash)); - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.outpoint.index)]).reverse()); - var scriptBytes = txin.script.buffer; - buffer = buffer.concat(Bitcoin.Util.numToVarInt(scriptBytes.length)); - buffer = buffer.concat(scriptBytes); - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)]).reverse()); - } - buffer = buffer.concat(Bitcoin.Util.numToVarInt(this.outs.length)); - for (var i = 0; i < this.outs.length; i++) { - var txout = this.outs[i]; - buffer = buffer.concat(txout.value); - var scriptBytes = txout.script.buffer; - buffer = buffer.concat(Bitcoin.Util.numToVarInt(scriptBytes.length)); - buffer = buffer.concat(scriptBytes); - } - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(this.lock_time)]).reverse()); - - return buffer; - }; - - var OP_CODESEPARATOR = 171; - - var SIGHASH_ALL = 1; - var SIGHASH_NONE = 2; - var SIGHASH_SINGLE = 3; - var SIGHASH_ANYONECANPAY = 80; - - /** - * Hash transaction for signing a specific input. - * - * Bitcoin uses a different hash for each signed transaction input. This - * method copies the transaction, makes the necessary changes based on the - * hashType, serializes and finally hashes the result. This hash can then be - * used to sign the transaction input in question. - */ - Transaction.prototype.hashTransactionForSignature = - function (connectedScript, inIndex, hashType) - { - var txTmp = this.clone(); - - // In case concatenating two scripts ends up with two codeseparators, - // or an extra one at the end, this prevents all those possible - // incompatibilities. - /*scriptCode = scriptCode.filter(function (val) { - return val !== OP_CODESEPARATOR; - });*/ - - // Blank out other inputs' signatures - for (var i = 0; i < txTmp.ins.length; i++) { - txTmp.ins[i].script = new Script(); - } - - txTmp.ins[inIndex].script = connectedScript; - - // Blank out some of the outputs - if ((hashType & 0x1f) == SIGHASH_NONE) { - txTmp.outs = []; - - // Let the others update at will - for (var i = 0; i < txTmp.ins.length; i++) - if (i != inIndex) - txTmp.ins[i].sequence = 0; - } else if ((hashType & 0x1f) == SIGHASH_SINGLE) { - // TODO: Implement - } - - // Blank out other inputs completely, not recommended for open transactions - if (hashType & SIGHASH_ANYONECANPAY) { - txTmp.ins = [txTmp.ins[inIndex]]; - } - - var buffer = txTmp.serialize(); - - buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(hashType)]).reverse()); - - var hash1 = Crypto.SHA256(buffer, {asBytes: true}); - - return Crypto.SHA256(hash1, {asBytes: true}); - }; - - /** - * Calculate and return the transaction's hash. - */ - Transaction.prototype.getHash = function () - { - var buffer = this.serialize(); - return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); - }; - - /** - * Create a copy of this transaction object. - */ - Transaction.prototype.clone = function () - { - var newTx = new Transaction(); - newTx.version = this.version; - newTx.lock_time = this.lock_time; - for (var i = 0; i < this.ins.length; i++) { - var txin = this.ins[i].clone(); - newTx.addInput(txin); - } - for (var i = 0; i < this.outs.length; i++) { - var txout = this.outs[i].clone(); - newTx.addOutput(txout); - } - return newTx; - }; - - /** - * Analyze how this transaction affects a wallet. - * - * Returns an object with properties 'impact', 'type' and 'addr'. - * - * 'impact' is an object, see Transaction#calcImpact. - * - * 'type' can be one of the following: - * - * recv: - * This is an incoming transaction, the wallet received money. - * 'addr' contains the first address in the wallet that receives money - * from this transaction. - * - * self: - * This is an internal transaction, money was sent within the wallet. - * 'addr' is undefined. - * - * sent: - * This is an outgoing transaction, money was sent out from the wallet. - * 'addr' contains the first external address, i.e. the recipient. - * - * other: - * This method was unable to detect what the transaction does. Either it - */ - Transaction.prototype.analyze = function (wallet) { - if (!(wallet instanceof Bitcoin.Wallet)) return null; - - var allFromMe = true, - allToMe = true, - firstRecvHash = null, - firstMeRecvHash = null, - firstSendHash = null; - - for (var i = this.outs.length-1; i >= 0; i--) { - var txout = this.outs[i]; - var hash = txout.script.simpleOutPubKeyHash(); - if (!wallet.hasHash(hash)) { - allToMe = false; - } else { - firstMeRecvHash = hash; - } - firstRecvHash = hash; - } - for (var i = this.ins.length-1; i >= 0; i--) { - var txin = this.ins[i]; - firstSendHash = txin.script.simpleInPubKeyHash(); - if (!wallet.hasHash(firstSendHash)) { - allFromMe = false; - break; - } - } - - var impact = this.calcImpact(wallet); - - var analysis = {}; - - analysis.impact = impact; - - if (impact.sign > 0 && impact.value.compareTo(BigInteger.ZERO) > 0) { - analysis.type = 'recv'; - analysis.addr = new Bitcoin.Address(firstMeRecvHash); - } else if (allFromMe && allToMe) { - analysis.type = 'self'; - } else if (allFromMe) { - analysis.type = 'sent'; - // TODO: Right now, firstRecvHash is the first output, which - if the - // transaction was not generated by this library could be the - // change address. - analysis.addr = new Bitcoin.Address(firstRecvHash); - } else { - analysis.type = "other"; - } - - return analysis; - }; - - /** - * Get a human-readable version of the data returned by Transaction#analyze. - * - * This is merely a convenience function. Clients should consider implementing - * this themselves based on their UI, I18N, etc. - */ - Transaction.prototype.getDescription = function (wallet) { - var analysis = this.analyze(wallet); - - if (!analysis) return ""; - - switch (analysis.type) { - case 'recv': - return "Received with "+analysis.addr; - break; - - case 'sent': - return "Payment to "+analysis.addr; - break; - - case 'self': - return "Payment to yourself"; - break; - - case 'other': - default: - return ""; - } - }; - - /** - * Get the total amount of a transaction's outputs. - */ - Transaction.prototype.getTotalOutValue = function () { - var totalValue = BigInteger.ZERO; - for (var j = 0; j < this.outs.length; j++) { - var txout = this.outs[j]; - totalValue = totalValue.add(Bitcoin.Util.valueToBigInt(txout.value)); - } - return totalValue; - }; - - /** - * Old name for Transaction#getTotalOutValue. - * - * @deprecated - */ - Transaction.prototype.getTotalValue = Transaction.prototype.getTotalOutValue; - - /** - * Calculates the impact a transaction has on this wallet. - * - * Based on the its public keys, the wallet will calculate the - * credit or debit of this transaction. - * - * It will return an object with two properties: - * - sign: 1 or -1 depending on sign of the calculated impact. - * - value: amount of calculated impact - * - * @returns Object Impact on wallet - */ - Transaction.prototype.calcImpact = function (wallet) { - if (!(wallet instanceof Bitcoin.Wallet)) return BigInteger.ZERO; - - // Calculate credit to us from all outputs - var valueOut = BigInteger.ZERO; - for (var j = 0; j < this.outs.length; j++) { - var txout = this.outs[j]; - var hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); - if (wallet.hasHash(hash)) { - valueOut = valueOut.add(Bitcoin.Util.valueToBigInt(txout.value)); - } - } - - // Calculate debit to us from all ins - var valueIn = BigInteger.ZERO; - for (var j = 0; j < this.ins.length; j++) { - var txin = this.ins[j]; - var hash = Crypto.util.bytesToBase64(txin.script.simpleInPubKeyHash()); - if (wallet.hasHash(hash)) { - var fromTx = wallet.txIndex[txin.outpoint.hash]; - if (fromTx) { - valueIn = valueIn.add(Bitcoin.Util.valueToBigInt(fromTx.outs[txin.outpoint.index].value)); - } - } - } - if (valueOut.compareTo(valueIn) >= 0) { - return { - sign: 1, - value: valueOut.subtract(valueIn) - }; - } else { - return { - sign: -1, - value: valueIn.subtract(valueOut) - }; - } - }; - - var TransactionIn = Bitcoin.TransactionIn = function (data) - { - this.outpoint = data.outpoint; - if (data.script instanceof Script) { - this.script = data.script; - } else { - this.script = new Script(data.script); - } - this.sequence = data.sequence; - }; - - TransactionIn.prototype.clone = function () - { - var newTxin = new TransactionIn({ - outpoint: { - hash: this.outpoint.hash, - index: this.outpoint.index - }, - script: this.script.clone(), - sequence: this.sequence - }); - return newTxin; - }; - - var TransactionOut = Bitcoin.TransactionOut = function (data) - { - if (data.script instanceof Script) { - this.script = data.script; - } else { - this.script = new Script(data.script); - } - - if (Bitcoin.Util.isArray(data.value)) { - this.value = data.value; - } else if ("string" == typeof data.value) { - var valueHex = (new BigInteger(data.value, 10)).toString(16); - while (valueHex.length < 16) valueHex = "0" + valueHex; - this.value = Crypto.util.hexToBytes(valueHex); - } - }; - - TransactionOut.prototype.clone = function () - { - var newTxout = new TransactionOut({ - script: this.script.clone(), - value: this.value.slice(0) - }); - return newTxout; - }; -})(); - - diff --git a/www/js/BitcoinJS/txdb.js b/www/js/BitcoinJS/txdb.js deleted file mode 100644 index 73ee835..0000000 --- a/www/js/BitcoinJS/txdb.js +++ /dev/null @@ -1,62 +0,0 @@ -var TransactionDatabase = function () { - this.txs = []; - this.txIndex = {}; -}; - -EventEmitter.augment(TransactionDatabase.prototype); - -TransactionDatabase.prototype.addTransaction = function (tx) { - this.addTransactionNoUpdate(tx); - $(this).trigger('update'); -}; - -TransactionDatabase.prototype.addTransactionNoUpdate = function (tx) { - // Return if transaction is already known - if (this.txIndex[tx.hash]) { - return; - } - - this.txs.push(new Bitcoin.Transaction(tx)); - this.txIndex[tx.hash] = tx; -}; - -TransactionDatabase.prototype.removeTransaction = function (hash) { - this.removeTransactionNoUpdate(hash); - $(this).trigger('update'); -}; - -TransactionDatabase.prototype.removeTransactionNoUpdate = function (hash) { - var tx = this.txIndex[hash]; - - if (!tx) { - // If the tx is not in the index, we don't actually waste our - // time looping through the array. - return; - } - - for (var i = 0, l = this.txs.length; i < l; i++) { - if (this.txs[i].hash == hash) { - this.txs.splice(i, 1); - break; - } - } - - delete this.txIndex[hash]; -}; - -TransactionDatabase.prototype.loadTransactions = function (txs) { - for (var i = 0; i < txs.length; i++) { - this.addTransactionNoUpdate(txs[i]); - } - $(this).trigger('update'); -}; - -TransactionDatabase.prototype.getTransactions = function () { - return this.txs; -}; - -TransactionDatabase.prototype.clear = function () { - this.txs = []; - this.txIndex = {}; - $(this).trigger('update'); -}; diff --git a/www/js/BitcoinJS/util.js b/www/js/BitcoinJS/util.js deleted file mode 100644 index 4c468a0..0000000 --- a/www/js/BitcoinJS/util.js +++ /dev/null @@ -1,228 +0,0 @@ -// BigInteger monkey patching -BigInteger.valueOf = nbv; - -/** - * Returns a byte array representation of the big integer. - * - * This returns the absolute of the contained value in big endian - * form. A value of zero results in an empty array. - */ -BigInteger.prototype.toByteArrayUnsigned = function () { - var ba = this.abs().toByteArray(); - if (ba.length) { - if (ba[0] == 0) { - ba = ba.slice(1); - } - return ba.map(function (v) { - return (v < 0) ? v + 256 : v; - }); - } else { - // Empty array, nothing to do - return ba; - } -}; - -/** - * Turns a byte array into a big integer. - * - * This function will interpret a byte array as a big integer in big - * endian notation and ignore leading zeros. - */ -BigInteger.fromByteArrayUnsigned = function (ba) { - if (!ba.length) { - return ba.valueOf(0); - } else if (ba[0] & 0x80) { - // Prepend a zero so the BigInteger class doesn't mistake this - // for a negative integer. - return new BigInteger([0].concat(ba)); - } else { - return new BigInteger(ba); - } -}; - -/** - * Converts big integer to signed byte representation. - * - * The format for this value uses a the most significant bit as a sign - * bit. If the most significant bit is already occupied by the - * absolute value, an extra byte is prepended and the sign bit is set - * there. - * - * Examples: - * - * 0 => 0x00 - * 1 => 0x01 - * -1 => 0x81 - * 127 => 0x7f - * -127 => 0xff - * 128 => 0x0080 - * -128 => 0x8080 - * 255 => 0x00ff - * -255 => 0x80ff - * 16300 => 0x3fac - * -16300 => 0xbfac - * 62300 => 0x00f35c - * -62300 => 0x80f35c - */ -BigInteger.prototype.toByteArraySigned = function () { - var val = this.abs().toByteArrayUnsigned(); - var neg = this.compareTo(BigInteger.ZERO) < 0; - - if (neg) { - if (val[0] & 0x80) { - val.unshift(0x80); - } else { - val[0] |= 0x80; - } - } else { - if (val[0] & 0x80) { - val.unshift(0x00); - } - } - - return val; -}; - -/** - * Parse a signed big integer byte representation. - * - * For details on the format please see BigInteger.toByteArraySigned. - */ -BigInteger.fromByteArraySigned = function (ba) { - // Check for negative value - if (ba[0] & 0x80) { - // Remove sign bit - ba[0] &= 0x7f; - - return BigInteger.fromByteArrayUnsigned(ba).negate(); - } else { - return BigInteger.fromByteArrayUnsigned(ba); - } -}; - -// Console ignore -var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", - "trace", "profile", "profileEnd"]; - -if ("undefined" == typeof window.console) window.console = {}; -for (var i = 0; i < names.length; ++i) - if ("undefined" == typeof window.console[names[i]]) - window.console[names[i]] = function() {}; - -// Bitcoin utility functions -Bitcoin.Util = { - /** - * Cross-browser compatibility version of Array.isArray. - */ - isArray: Array.isArray || function(o) - { - return Object.prototype.toString.call(o) === '[object Array]'; - }, - - /** - * Create an array of a certain length filled with a specific value. - */ - makeFilledArray: function (len, val) - { - var array = []; - var i = 0; - while (i < len) { - array[i++] = val; - } - return array; - }, - - /** - * Turn an integer into a "var_int". - * - * "var_int" is a variable length integer used by Bitcoin's binary format. - * - * Returns a byte array. - */ - numToVarInt: function (i) - { - if (i < 0xfd) { - // unsigned char - return [i]; - } else if (i <= 1<<16) { - // unsigned short (LE) - return [0xfd, i >>> 8, i & 255]; - } else if (i <= 1<<32) { - // unsigned int (LE) - return [0xfe].concat(Crypto.util.wordsToBytes([i])); - } else { - // unsigned long long (LE) - return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i])); - } - }, - - /** - * Parse a Bitcoin value byte array, returning a BigInteger. - */ - valueToBigInt: function (valueBuffer) - { - if (valueBuffer instanceof BigInteger) return valueBuffer; - - // Prepend zero byte to prevent interpretation as negative integer - return BigInteger.fromByteArrayUnsigned(valueBuffer); - }, - - /** - * Format a Bitcoin value as a string. - * - * Takes a BigInteger or byte-array and returns that amount of Bitcoins in a - * nice standard formatting. - * - * Examples: - * 12.3555 - * 0.1234 - * 900.99998888 - * 34.00 - */ - formatValue: function (valueBuffer) { - var value = this.valueToBigInt(valueBuffer).toString(); - var integerPart = value.length > 8 ? value.substr(0, value.length-8) : '0'; - var decimalPart = value.length > 8 ? value.substr(value.length-8) : value; - while (decimalPart.length < 8) decimalPart = "0"+decimalPart; - decimalPart = decimalPart.replace(/0*$/, ''); - while (decimalPart.length < 2) decimalPart += "0"; - return integerPart+"."+decimalPart; - }, - - /** - * Parse a floating point string as a Bitcoin value. - * - * Keep in mind that parsing user input is messy. You should always display - * the parsed value back to the user to make sure we understood his input - * correctly. - */ - parseValue: function (valueString) { - // TODO: Detect other number formats (e.g. comma as decimal separator) - var valueComp = valueString.split('.'); - var integralPart = valueComp[0]; - var fractionalPart = valueComp[1] || "0"; - while (fractionalPart.length < 8) fractionalPart += "0"; - fractionalPart = fractionalPart.replace(/^0+/g, ''); - var value = BigInteger.valueOf(parseInt(integralPart)); - value = value.multiply(BigInteger.valueOf(100000000)); - value = value.add(BigInteger.valueOf(parseInt(fractionalPart))); - return value; - }, - - /** - * Calculate RIPEMD160(SHA256(data)). - * - * Takes an arbitrary byte array as inputs and returns the hash as a byte - * array. - */ - sha256ripe160: function (data) { - return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true}); - } -}; - -for (var i in Crypto.util) { - if (Crypto.util.hasOwnProperty(i)) { - Bitcoin.Util[i] = Crypto.util[i]; - } -} diff --git a/www/js/BitcoinJS/wallet.js b/www/js/BitcoinJS/wallet.js deleted file mode 100644 index 501ec34..0000000 --- a/www/js/BitcoinJS/wallet.js +++ /dev/null @@ -1,308 +0,0 @@ -Bitcoin.Wallet = (function () { - var Script = Bitcoin.Script, - TransactionIn = Bitcoin.TransactionIn, - TransactionOut = Bitcoin.TransactionOut; - - var Wallet = function () { - // Keychain - // - // The keychain is stored as a var in this closure to make accidental - // serialization less likely. - // - // Any functions accessing this value therefore have to be defined in - // the closure of this constructor. - var keys = []; - - // Public hashes of our keys - this.addressHashes = []; - - // Transaction data - this.txIndex = {}; - this.unspentOuts = []; - - // Other fields - this.addressPointer = 0; - - /** - * Add a key to the keychain. - * - * The corresponding public key can be provided as a second parameter. This - * adds it to the cache in the ECKey object and avoid the need to - * expensively calculate it later. - */ - this.addKey = function (key, pub) { - if (!(key instanceof Bitcoin.ECKey)) { - key = new Bitcoin.ECKey(key); - } - keys.push(key); - - if (pub) { - if ("string" === typeof pub) { - pub = Crypto.util.base64ToBytes(pub); - } - key.setPub(pub); - } - - this.addressHashes.push(key.getBitcoinAddress().getHashBase64()); - }; - - /** - * Add multiple keys at once. - */ - this.addKeys = function (keys, pubs) { - if ("string" === typeof keys) { - keys = keys.split(','); - } - if ("string" === typeof pubs) { - pubs = pubs.split(','); - } - var i; - if (Array.isArray(pubs) && keys.length == pubs.length) { - for (i = 0; i < keys.length; i++) { - this.addKey(keys[i], pubs[i]); - } - } else { - for (i = 0; i < keys.length; i++) { - this.addKey(keys[i]); - } - } - }; - - /** - * Get the key chain. - * - * Returns an array of base64-encoded private values. - */ - this.getKeys = function () { - var serializedWallet = []; - - for (var i = 0; i < keys.length; i++) { - serializedWallet.push(keys[i].toString('base64')); - } - - return serializedWallet; - }; - - /** - * Get the public keys. - * - * Returns an array of base64-encoded public keys. - */ - this.getPubKeys = function () { - var pubs = []; - - for (var i = 0; i < keys.length; i++) { - pubs.push(Crypto.util.bytesToBase64(keys[i].getPub())); - } - - return pubs; - }; - - /** - * Delete all keys. - */ - this.clear = function () { - keys = []; - }; - - /** - * Return the number of keys in this wallet. - */ - this.getLength = function () { - return keys.length; - }; - - /** - * Get the addresses for this wallet. - * - * Returns an array of Address objects. - */ - this.getAllAddresses = function () { - var addresses = []; - for (var i = 0; i < keys.length; i++) { - addresses.push(keys[i].getBitcoinAddress()); - } - return addresses; - }; - - this.getCurAddress = function () { - if (keys[this.addressPointer]) { - return keys[this.addressPointer].getBitcoinAddress(); - } else { - return null; - } - }; - - /** - * Go to the next address. - * - * If there are no more new addresses available, one will be generated - * automatically. - */ - this.getNextAddress = function () { - this.addressPointer++; - if (!keys[this.addressPointer]) { - this.generateAddress(); - } - return keys[this.addressPointer].getBitcoinAddress(); - }; - - /** - * Sign a hash with a key. - * - * This method expects the pubKeyHash as the first parameter and the hash - * to be signed as the second parameter. - */ - this.signWithKey = function (pubKeyHash, hash) { - pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); - for (var i = 0; i < this.addressHashes.length; i++) { - if (this.addressHashes[i] == pubKeyHash) { - return keys[i].sign(hash); - } - } - throw new Error("Missing key for signature"); - }; - - /** - * Retrieve the corresponding pubKey for a pubKeyHash. - * - * This function only works if the pubKey in question is part of this - * wallet. - */ - this.getPubKeyFromHash = function (pubKeyHash) { - pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); - for (var i = 0; i < this.addressHashes.length; i++) { - if (this.addressHashes[i] == pubKeyHash) { - return keys[i].getPub(); - } - } - throw new Error("Hash unknown"); - }; - }; - - Wallet.prototype.generateAddress = function () { - this.addKey(new Bitcoin.ECKey()); - }; - - /** - * Add a transaction to the wallet's processed transaction. - * - * This will add a transaction to the wallet, updating its balance and - * available unspent outputs. - */ - Wallet.prototype.process = function (tx) { - if (this.txIndex[tx.hash]) return; - - var j; - var k; - var hash; - // Gather outputs - for (j = 0; j < tx.outs.length; j++) { - var txout = new TransactionOut(tx.outs[j]); - hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); - for (k = 0; k < this.addressHashes.length; k++) { - if (this.addressHashes[k] === hash) { - this.unspentOuts.push({tx: tx, index: j, out: txout}); - break; - } - } - } - - // Remove spent outputs - for (j = 0; j < tx.ins.length; j++) { - var txin = new TransactionIn(tx.ins[j]); - var pubkey = txin.script.simpleInPubKey(); - hash = Crypto.util.bytesToBase64(Bitcoin.Util.sha256ripe160(pubkey)); - for (k = 0; k < this.addressHashes.length; k++) { - if (this.addressHashes[k] === hash) { - for (var l = 0; l < this.unspentOuts.length; l++) { - if (txin.outpoint.hash == this.unspentOuts[l].tx.hash && - txin.outpoint.index == this.unspentOuts[l].index) { - this.unspentOuts.splice(l, 1); - } - } - break; - } - } - } - - // Index transaction - this.txIndex[tx.hash] = tx; - }; - - Wallet.prototype.getBalance = function () { - var balance = BigInteger.valueOf(0); - for (var i = 0; i < this.unspentOuts.length; i++) { - var txout = this.unspentOuts[i].out; - balance = balance.add(Bitcoin.Util.valueToBigInt(txout.value)); - } - return balance; - }; - - Wallet.prototype.createSend = function (address, sendValue, feeValue) { - var selectedOuts = []; - var txValue = sendValue.add(feeValue); - var availableValue = BigInteger.ZERO; - var i; - for (i = 0; i < this.unspentOuts.length; i++) { - selectedOuts.push(this.unspentOuts[i]); - availableValue = availableValue.add(Bitcoin.Util.valueToBigInt(this.unspentOuts[i].out.value)); - - if (availableValue.compareTo(txValue) >= 0) break; - } - - if (availableValue.compareTo(txValue) < 0) { - throw new Error('Insufficient funds.'); - } - - - var changeValue = availableValue.subtract(txValue); - - var sendTx = new Bitcoin.Transaction(); - - for (i = 0; i < selectedOuts.length; i++) { - sendTx.addInput(selectedOuts[i].tx, selectedOuts[i].index); - } - - sendTx.addOutput(address, sendValue); - if (changeValue.compareTo(BigInteger.ZERO) > 0) { - sendTx.addOutput(this.getNextAddress(), changeValue); - } - - var hashType = 1; // SIGHASH_ALL - - for (i = 0; i < sendTx.ins.length; i++) { - var hash = sendTx.hashTransactionForSignature(selectedOuts[i].out.script, i, hashType); - var pubKeyHash = selectedOuts[i].out.script.simpleOutPubKeyHash(); - var signature = this.signWithKey(pubKeyHash, hash); - - // Append hash type - signature.push(parseInt(hashType, 10)); - - sendTx.ins[i].script = Script.createInputScript(signature, this.getPubKeyFromHash(pubKeyHash)); - } - - return sendTx; - }; - - Wallet.prototype.clearTransactions = function () { - this.txIndex = {}; - this.unspentOuts = []; - }; - - /** - * Check to see if a pubKeyHash belongs to this wallet. - */ - Wallet.prototype.hasHash = function (hash) { - if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToBase64(hash); - - // TODO: Just create an object with base64 hashes as keys for faster lookup - for (var k = 0; k < this.addressHashes.length; k++) { - if (this.addressHashes[k] === hash) return true; - } - return false; - }; - - return Wallet; -})(); - diff --git a/www/js/angular.js b/www/js/angular.js deleted file mode 100644 index a860c85..0000000 --- a/www/js/angular.js +++ /dev/null @@ -1,14847 +0,0 @@ -/** - * @license AngularJS v1.0.7 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, document, undefined) { -'use strict'; - -//////////////////////////////////// - -/** - * @ngdoc function - * @name angular.lowercase - * @function - * - * @description Converts the specified string to lowercase. - * @param {string} string String to be converted to lowercase. - * @returns {string} Lowercased string. - */ -var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; - - -/** - * @ngdoc function - * @name angular.uppercase - * @function - * - * @description Converts the specified string to uppercase. - * @param {string} string String to be converted to uppercase. - * @returns {string} Uppercased string. - */ -var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; - - -var manualLowercase = function(s) { - return isString(s) - ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) - : s; -}; -var manualUppercase = function(s) { - return isString(s) - ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) - : s; -}; - - -// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish -// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods -// with correct but slower alternatives. -if ('i' !== 'I'.toLowerCase()) { - lowercase = manualLowercase; - uppercase = manualUppercase; -} - - -var /** holds major version number for IE or NaN for real browsers */ - msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]), - jqLite, // delay binding since jQuery could be loaded after us. - jQuery, // delay binding - slice = [].slice, - push = [].push, - toString = Object.prototype.toString, - - /** @name angular */ - angular = window.angular || (window.angular = {}), - angularModule, - nodeName_, - uid = ['0', '0', '0']; - - -/** - * @private - * @param {*} obj - * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...) - */ -function isArrayLike(obj) { - if (!obj || (typeof obj.length !== 'number')) return false; - - // We have on object which has length property. Should we treat it as array? - if (typeof obj.hasOwnProperty != 'function' && - typeof obj.constructor != 'function') { - // This is here for IE8: it is a bogus object treat it as array; - return true; - } else { - return obj instanceof JQLite || // JQLite - (jQuery && obj instanceof jQuery) || // jQuery - toString.call(obj) !== '[object Object]' || // some browser native object - typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj) - } -} - - -/** - * @ngdoc function - * @name angular.forEach - * @function - * - * @description - * Invokes the `iterator` function once for each item in `obj` collection, which can be either an - * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value` - * is the value of an object property or an array element and `key` is the object property key or - * array element index. Specifying a `context` for the function is optional. - * - * Note: this function was previously known as `angular.foreach`. - * -
-     var values = {name: 'misko', gender: 'male'};
-     var log = [];
-     angular.forEach(values, function(value, key){
-       this.push(key + ': ' + value);
-     }, log);
-     expect(log).toEqual(['name: misko', 'gender:male']);
-   
- * - * @param {Object|Array} obj Object to iterate over. - * @param {Function} iterator Iterator function. - * @param {Object=} context Object to become context (`this`) for the iterator function. - * @returns {Object|Array} Reference to `obj`. - */ -function forEach(obj, iterator, context) { - var key; - if (obj) { - if (isFunction(obj)){ - for (key in obj) { - if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key); - } - } - } else if (obj.forEach && obj.forEach !== forEach) { - obj.forEach(iterator, context); - } else if (isArrayLike(obj)) { - for (key = 0; key < obj.length; key++) - iterator.call(context, obj[key], key); - } else { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key); - } - } - } - } - return obj; -} - -function sortedKeys(obj) { - var keys = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - keys.push(key); - } - } - return keys.sort(); -} - -function forEachSorted(obj, iterator, context) { - var keys = sortedKeys(obj); - for ( var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); - } - return keys; -} - - -/** - * when using forEach the params are value, key, but it is often useful to have key, value. - * @param {function(string, *)} iteratorFn - * @returns {function(*, string)} - */ -function reverseParams(iteratorFn) { - return function(value, key) { iteratorFn(key, value) }; -} - -/** - * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric - * characters such as '012ABC'. The reason why we are not using simply a number counter is that - * the number string gets longer over time, and it can also overflow, where as the nextId - * will grow much slower, it is a string, and it will never overflow. - * - * @returns an unique alpha-numeric string - */ -function nextUid() { - var index = uid.length; - var digit; - - while(index) { - index--; - digit = uid[index].charCodeAt(0); - if (digit == 57 /*'9'*/) { - uid[index] = 'A'; - return uid.join(''); - } - if (digit == 90 /*'Z'*/) { - uid[index] = '0'; - } else { - uid[index] = String.fromCharCode(digit + 1); - return uid.join(''); - } - } - uid.unshift('0'); - return uid.join(''); -} - - -/** - * Set or clear the hashkey for an object. - * @param obj object - * @param h the hashkey (!truthy to delete the hashkey) - */ -function setHashKey(obj, h) { - if (h) { - obj.$$hashKey = h; - } - else { - delete obj.$$hashKey; - } -} - -/** - * @ngdoc function - * @name angular.extend - * @function - * - * @description - * Extends the destination object `dst` by copying all of the properties from the `src` object(s) - * to `dst`. You can specify multiple `src` objects. - * - * @param {Object} dst Destination object. - * @param {...Object} src Source object(s). - * @returns {Object} Reference to `dst`. - */ -function extend(dst) { - var h = dst.$$hashKey; - forEach(arguments, function(obj){ - if (obj !== dst) { - forEach(obj, function(value, key){ - dst[key] = value; - }); - } - }); - - setHashKey(dst,h); - return dst; -} - -function int(str) { - return parseInt(str, 10); -} - - -function inherit(parent, extra) { - return extend(new (extend(function() {}, {prototype:parent}))(), extra); -} - - -/** - * @ngdoc function - * @name angular.noop - * @function - * - * @description - * A function that performs no operations. This function can be useful when writing code in the - * functional style. -
-     function foo(callback) {
-       var result = calculateResult();
-       (callback || angular.noop)(result);
-     }
-   
- */ -function noop() {} -noop.$inject = []; - - -/** - * @ngdoc function - * @name angular.identity - * @function - * - * @description - * A function that returns its first argument. This function is useful when writing code in the - * functional style. - * -
-     function transformer(transformationFn, value) {
-       return (transformationFn || identity)(value);
-     };
-   
- */ -function identity($) {return $;} -identity.$inject = []; - - -function valueFn(value) {return function() {return value;};} - -/** - * @ngdoc function - * @name angular.isUndefined - * @function - * - * @description - * Determines if a reference is undefined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is undefined. - */ -function isUndefined(value){return typeof value == 'undefined';} - - -/** - * @ngdoc function - * @name angular.isDefined - * @function - * - * @description - * Determines if a reference is defined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is defined. - */ -function isDefined(value){return typeof value != 'undefined';} - - -/** - * @ngdoc function - * @name angular.isObject - * @function - * - * @description - * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not - * considered to be objects. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Object` but not `null`. - */ -function isObject(value){return value != null && typeof value == 'object';} - - -/** - * @ngdoc function - * @name angular.isString - * @function - * - * @description - * Determines if a reference is a `String`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `String`. - */ -function isString(value){return typeof value == 'string';} - - -/** - * @ngdoc function - * @name angular.isNumber - * @function - * - * @description - * Determines if a reference is a `Number`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Number`. - */ -function isNumber(value){return typeof value == 'number';} - - -/** - * @ngdoc function - * @name angular.isDate - * @function - * - * @description - * Determines if a value is a date. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Date`. - */ -function isDate(value){ - return toString.apply(value) == '[object Date]'; -} - - -/** - * @ngdoc function - * @name angular.isArray - * @function - * - * @description - * Determines if a reference is an `Array`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Array`. - */ -function isArray(value) { - return toString.apply(value) == '[object Array]'; -} - - -/** - * @ngdoc function - * @name angular.isFunction - * @function - * - * @description - * Determines if a reference is a `Function`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Function`. - */ -function isFunction(value){return typeof value == 'function';} - - -/** - * Checks if `obj` is a window object. - * - * @private - * @param {*} obj Object to check - * @returns {boolean} True if `obj` is a window obj. - */ -function isWindow(obj) { - return obj && obj.document && obj.location && obj.alert && obj.setInterval; -} - - -function isScope(obj) { - return obj && obj.$evalAsync && obj.$watch; -} - - -function isFile(obj) { - return toString.apply(obj) === '[object File]'; -} - - -function isBoolean(value) { - return typeof value == 'boolean'; -} - - -function trim(value) { - return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; -} - -/** - * @ngdoc function - * @name angular.isElement - * @function - * - * @description - * Determines if a reference is a DOM element (or wrapped jQuery element). - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). - */ -function isElement(node) { - return node && - (node.nodeName // we are a direct element - || (node.bind && node.find)); // we have a bind and find method part of jQuery API -} - -/** - * @param str 'key1,key2,...' - * @returns {object} in the form of {key1:true, key2:true, ...} - */ -function makeMap(str){ - var obj = {}, items = str.split(","), i; - for ( i = 0; i < items.length; i++ ) - obj[ items[i] ] = true; - return obj; -} - - -if (msie < 9) { - nodeName_ = function(element) { - element = element.nodeName ? element : element[0]; - return (element.scopeName && element.scopeName != 'HTML') - ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName; - }; -} else { - nodeName_ = function(element) { - return element.nodeName ? element.nodeName : element[0].nodeName; - }; -} - - -function map(obj, iterator, context) { - var results = []; - forEach(obj, function(value, index, list) { - results.push(iterator.call(context, value, index, list)); - }); - return results; -} - - -/** - * @description - * Determines the number of elements in an array, the number of properties an object has, or - * the length of a string. - * - * Note: This function is used to augment the Object type in Angular expressions. See - * {@link angular.Object} for more information about Angular arrays. - * - * @param {Object|Array|string} obj Object, array, or string to inspect. - * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object - * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array. - */ -function size(obj, ownPropsOnly) { - var size = 0, key; - - if (isArray(obj) || isString(obj)) { - return obj.length; - } else if (isObject(obj)){ - for (key in obj) - if (!ownPropsOnly || obj.hasOwnProperty(key)) - size++; - } - - return size; -} - - -function includes(array, obj) { - return indexOf(array, obj) != -1; -} - -function indexOf(array, obj) { - if (array.indexOf) return array.indexOf(obj); - - for ( var i = 0; i < array.length; i++) { - if (obj === array[i]) return i; - } - return -1; -} - -function arrayRemove(array, value) { - var index = indexOf(array, value); - if (index >=0) - array.splice(index, 1); - return value; -} - -function isLeafNode (node) { - if (node) { - switch (node.nodeName) { - case "OPTION": - case "PRE": - case "TITLE": - return true; - } - } - return false; -} - -/** - * @ngdoc function - * @name angular.copy - * @function - * - * @description - * Creates a deep copy of `source`, which should be an object or an array. - * - * * If no destination is supplied, a copy of the object or array is created. - * * If a destination is provided, all of its elements (for array) or properties (for objects) - * are deleted and then all elements/properties from the source are copied to it. - * * If `source` is not an object or array, `source` is returned. - * - * Note: this function is used to augment the Object type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {*} source The source that will be used to make a copy. - * Can be any type, including primitives, `null`, and `undefined`. - * @param {(Object|Array)=} destination Destination into which the source is copied. If - * provided, must be of the same type as `source`. - * @returns {*} The copy or updated `destination`, if `destination` was specified. - */ -function copy(source, destination){ - if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope"); - if (!destination) { - destination = source; - if (source) { - if (isArray(source)) { - destination = copy(source, []); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isObject(source)) { - destination = copy(source, {}); - } - } - } else { - if (source === destination) throw Error("Can't copy equivalent objects or arrays"); - if (isArray(source)) { - destination.length = 0; - for ( var i = 0; i < source.length; i++) { - destination.push(copy(source[i])); - } - } else { - var h = destination.$$hashKey; - forEach(destination, function(value, key){ - delete destination[key]; - }); - for ( var key in source) { - destination[key] = copy(source[key]); - } - setHashKey(destination,h); - } - } - return destination; -} - -/** - * Create a shallow copy of an object - */ -function shallowCopy(src, dst) { - dst = dst || {}; - - for(var key in src) { - if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') { - dst[key] = src[key]; - } - } - - return dst; -} - - -/** - * @ngdoc function - * @name angular.equals - * @function - * - * @description - * Determines if two objects or two values are equivalent. Supports value types, arrays and - * objects. - * - * Two objects or values are considered equivalent if at least one of the following is true: - * - * * Both objects or values pass `===` comparison. - * * Both objects or values are of the same type and all of their properties pass `===` comparison. - * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal) - * - * During a property comparision, properties of `function` type and properties with names - * that begin with `$` are ignored. - * - * Scope and DOMWindow objects are being compared only by identify (`===`). - * - * @param {*} o1 Object or value to compare. - * @param {*} o2 Object or value to compare. - * @returns {boolean} True if arguments are equal. - */ -function equals(o1, o2) { - if (o1 === o2) return true; - if (o1 === null || o2 === null) return false; - if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN - var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == 'object') { - if (isArray(o1)) { - if ((length = o1.length) == o2.length) { - for(key=0; key 2 ? sliceArgs(arguments, 2) : []; - if (isFunction(fn) && !(fn instanceof RegExp)) { - return curryArgs.length - ? function() { - return arguments.length - ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0))) - : fn.apply(self, curryArgs); - } - : function() { - return arguments.length - ? fn.apply(self, arguments) - : fn.call(self); - }; - } else { - // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) - return fn; - } -} - - -function toJsonReplacer(key, value) { - var val = value; - - if (/^\$+/.test(key)) { - val = undefined; - } else if (isWindow(value)) { - val = '$WINDOW'; - } else if (value && document === value) { - val = '$DOCUMENT'; - } else if (isScope(value)) { - val = '$SCOPE'; - } - - return val; -} - - -/** - * @ngdoc function - * @name angular.toJson - * @function - * - * @description - * Serializes input into a JSON-formatted string. - * - * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. - * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace. - * @returns {string} Jsonified string representing `obj`. - */ -function toJson(obj, pretty) { - return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null); -} - - -/** - * @ngdoc function - * @name angular.fromJson - * @function - * - * @description - * Deserializes a JSON string. - * - * @param {string} json JSON string to deserialize. - * @returns {Object|Array|Date|string|number} Deserialized thingy. - */ -function fromJson(json) { - return isString(json) - ? JSON.parse(json) - : json; -} - - -function toBoolean(value) { - if (value && value.length !== 0) { - var v = lowercase("" + value); - value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]'); - } else { - value = false; - } - return value; -} - -/** - * @returns {string} Returns the string representation of the element. - */ -function startingTag(element) { - element = jqLite(element).clone(); - try { - // turns out IE does not let you set .html() on elements which - // are not allowed to have children. So we just ignore it. - element.html(''); - } catch(e) {} - // As Per DOM Standards - var TEXT_NODE = 3; - var elemHtml = jqLite('
').append(element).html(); - try { - return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) : - elemHtml. - match(/^(<[^>]+>)/)[1]. - replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); - } catch(e) { - return lowercase(elemHtml); - } - -} - - -///////////////////////////////////////////////// - -/** - * Parses an escaped url query string into key-value pairs. - * @returns Object.<(string|boolean)> - */ -function parseKeyValue(/**string*/keyValue) { - var obj = {}, key_value, key; - forEach((keyValue || "").split('&'), function(keyValue){ - if (keyValue) { - key_value = keyValue.split('='); - key = decodeURIComponent(key_value[0]); - obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true; - } - }); - return obj; -} - -function toKeyValue(obj) { - var parts = []; - forEach(obj, function(value, key) { - parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true))); - }); - return parts.length ? parts.join('&') : ''; -} - - -/** - * We need our custom method because encodeURIComponent is too agressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); -} - - -/** - * This method is intended for encoding *key* or *value* parts of query component. We need a custom - * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be - * encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); -} - - -/** - * @ngdoc directive - * @name ng.directive:ngApp - * - * @element ANY - * @param {angular.Module} ngApp an optional application - * {@link angular.module module} name to load. - * - * @description - * - * Use this directive to auto-bootstrap an application. Only - * one directive can be used per HTML document. The directive - * designates the root of the application and is typically placed - * at the root of the page. - * - * In the example below if the `ngApp` directive would not be placed - * on the `html` element then the document would not be compiled - * and the `{{ 1+2 }}` would not be resolved to `3`. - * - * `ngApp` is the easiest way to bootstrap an application. - * - - - I can add: 1 + 2 = {{ 1+2 }} - - - * - */ -function angularInit(element, bootstrap) { - var elements = [element], - appElement, - module, - names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], - NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; - - function append(element) { - element && elements.push(element); - } - - forEach(names, function(name) { - names[name] = true; - append(document.getElementById(name)); - name = name.replace(':', '\\:'); - if (element.querySelectorAll) { - forEach(element.querySelectorAll('.' + name), append); - forEach(element.querySelectorAll('.' + name + '\\:'), append); - forEach(element.querySelectorAll('[' + name + ']'), append); - } - }); - - forEach(elements, function(element) { - if (!appElement) { - var className = ' ' + element.className + ' '; - var match = NG_APP_CLASS_REGEXP.exec(className); - if (match) { - appElement = element; - module = (match[2] || '').replace(/\s+/g, ','); - } else { - forEach(element.attributes, function(attr) { - if (!appElement && names[attr.name]) { - appElement = element; - module = attr.value; - } - }); - } - } - }); - if (appElement) { - bootstrap(appElement, module ? [module] : []); - } -} - -/** - * @ngdoc function - * @name angular.bootstrap - * @description - * Use this function to manually start up angular application. - * - * See: {@link guide/bootstrap Bootstrap} - * - * @param {Element} element DOM element which is the root of angular application. - * @param {Array=} modules an array of module declarations. See: {@link angular.module modules} - * @returns {AUTO.$injector} Returns the newly created injector for this app. - */ -function bootstrap(element, modules) { - var resumeBootstrapInternal = function() { - element = jqLite(element); - modules = modules || []; - modules.unshift(['$provide', function($provide) { - $provide.value('$rootElement', element); - }]); - modules.unshift('ng'); - var injector = createInjector(modules); - injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', - function(scope, element, compile, injector) { - scope.$apply(function() { - element.data('$injector', injector); - compile(element)(scope); - }); - }] - ); - return injector; - }; - - var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; - - if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { - return resumeBootstrapInternal(); - } - - window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); - angular.resumeBootstrap = function(extraModules) { - forEach(extraModules, function(module) { - modules.push(module); - }); - resumeBootstrapInternal(); - }; -} - -var SNAKE_CASE_REGEXP = /[A-Z]/g; -function snake_case(name, separator){ - separator = separator || '_'; - return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { - return (pos ? separator : '') + letter.toLowerCase(); - }); -} - -function bindJQuery() { - // bind to jQuery if present; - jQuery = window.jQuery; - // reset to jQuery or default to us. - if (jQuery) { - jqLite = jQuery; - extend(jQuery.fn, { - scope: JQLitePrototype.scope, - controller: JQLitePrototype.controller, - injector: JQLitePrototype.injector, - inheritedData: JQLitePrototype.inheritedData - }); - JQLitePatchJQueryRemove('remove', true); - JQLitePatchJQueryRemove('empty'); - JQLitePatchJQueryRemove('html'); - } else { - jqLite = JQLite; - } - angular.element = jqLite; -} - -/** - * throw error if the argument is falsy. - */ -function assertArg(arg, name, reason) { - if (!arg) { - throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required")); - } - return arg; -} - -function assertArgFn(arg, name, acceptArrayAnnotation) { - if (acceptArrayAnnotation && isArray(arg)) { - arg = arg[arg.length - 1]; - } - - assertArg(isFunction(arg), name, 'not a function, got ' + - (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg)); - return arg; -} - -/** - * @ngdoc interface - * @name angular.Module - * @description - * - * Interface for configuring angular {@link angular.module modules}. - */ - -function setupModuleLoader(window) { - - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); - } - - return ensure(ensure(window, 'angular', Object), 'module', function() { - /** @type {Object.} */ - var modules = {}; - - /** - * @ngdoc function - * @name angular.module - * @description - * - * The `angular.module` is a global place for creating and registering Angular modules. All - * modules (angular core or 3rd party) that should be available to an application must be - * registered using this mechanism. - * - * - * # Module - * - * A module is a collocation of services, directives, filters, and configuration information. Module - * is used to configure the {@link AUTO.$injector $injector}. - * - *
-     * // Create a new module
-     * var myModule = angular.module('myModule', []);
-     *
-     * // register a new service
-     * myModule.value('appName', 'MyCoolApp');
-     *
-     * // configure existing services inside initialization blocks.
-     * myModule.config(function($locationProvider) {
-     *   // Configure existing providers
-     *   $locationProvider.hashPrefix('!');
-     * });
-     * 
- * - * Then you can create an injector and load your modules like this: - * - *
-     * var injector = angular.injector(['ng', 'MyModule'])
-     * 
- * - * However it's more likely that you'll just use - * {@link ng.directive:ngApp ngApp} or - * {@link angular.bootstrap} to simplify this process for you. - * - * @param {!string} name The name of the module to create or retrieve. - * @param {Array.=} requires If specified then new module is being created. If unspecified then the - * the module is being retrieved for further configuration. - * @param {Function} configFn Optional configuration function for the module. Same as - * {@link angular.Module#config Module#config()}. - * @returns {module} new module with the {@link angular.Module} api. - */ - return function module(name, requires, configFn) { - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; - } - return ensure(modules, name, function() { - if (!requires) { - throw Error('No module: ' + name); - } - - /** @type {!Array.>} */ - var invokeQueue = []; - - /** @type {!Array.} */ - var runBlocks = []; - - var config = invokeLater('$injector', 'invoke'); - - /** @type {angular.Module} */ - var moduleInstance = { - // Private state - _invokeQueue: invokeQueue, - _runBlocks: runBlocks, - - /** - * @ngdoc property - * @name angular.Module#requires - * @propertyOf angular.Module - * @returns {Array.} List of module names which must be loaded before this module. - * @description - * Holds the list of modules which the injector will load before the current module is loaded. - */ - requires: requires, - - /** - * @ngdoc property - * @name angular.Module#name - * @propertyOf angular.Module - * @returns {string} Name of the module. - * @description - */ - name: name, - - - /** - * @ngdoc method - * @name angular.Module#provider - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerType Construction function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#provider $provide.provider()}. - */ - provider: invokeLater('$provide', 'provider'), - - /** - * @ngdoc method - * @name angular.Module#factory - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerFunction Function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#factory $provide.factory()}. - */ - factory: invokeLater('$provide', 'factory'), - - /** - * @ngdoc method - * @name angular.Module#service - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} constructor A constructor function that will be instantiated. - * @description - * See {@link AUTO.$provide#service $provide.service()}. - */ - service: invokeLater('$provide', 'service'), - - /** - * @ngdoc method - * @name angular.Module#value - * @methodOf angular.Module - * @param {string} name service name - * @param {*} object Service instance object. - * @description - * See {@link AUTO.$provide#value $provide.value()}. - */ - value: invokeLater('$provide', 'value'), - - /** - * @ngdoc method - * @name angular.Module#constant - * @methodOf angular.Module - * @param {string} name constant name - * @param {*} object Constant value. - * @description - * Because the constant are fixed, they get applied before other provide methods. - * See {@link AUTO.$provide#constant $provide.constant()}. - */ - constant: invokeLater('$provide', 'constant', 'unshift'), - - /** - * @ngdoc method - * @name angular.Module#filter - * @methodOf angular.Module - * @param {string} name Filter name. - * @param {Function} filterFactory Factory function for creating new instance of filter. - * @description - * See {@link ng.$filterProvider#register $filterProvider.register()}. - */ - filter: invokeLater('$filterProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#controller - * @methodOf angular.Module - * @param {string} name Controller name. - * @param {Function} constructor Controller constructor function. - * @description - * See {@link ng.$controllerProvider#register $controllerProvider.register()}. - */ - controller: invokeLater('$controllerProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#directive - * @methodOf angular.Module - * @param {string} name directive name - * @param {Function} directiveFactory Factory function for creating new instance of - * directives. - * @description - * See {@link ng.$compileProvider#directive $compileProvider.directive()}. - */ - directive: invokeLater('$compileProvider', 'directive'), - - /** - * @ngdoc method - * @name angular.Module#config - * @methodOf angular.Module - * @param {Function} configFn Execute this function on module load. Useful for service - * configuration. - * @description - * Use this method to register work which needs to be performed on module loading. - */ - config: config, - - /** - * @ngdoc method - * @name angular.Module#run - * @methodOf angular.Module - * @param {Function} initializationFn Execute this function after injector creation. - * Useful for application initialization. - * @description - * Use this method to register work which should be performed when the injector is done - * loading all modules. - */ - run: function(block) { - runBlocks.push(block); - return this; - } - }; - - if (configFn) { - config(configFn); - } - - return moduleInstance; - - /** - * @param {string} provider - * @param {string} method - * @param {String=} insertMethod - * @returns {angular.Module} - */ - function invokeLater(provider, method, insertMethod) { - return function() { - invokeQueue[insertMethod || 'push']([provider, method, arguments]); - return moduleInstance; - } - } - }); - }; - }); - -} - -/** - * @ngdoc property - * @name angular.version - * @description - * An object that contains information about the current AngularJS version. This object has the - * following properties: - * - * - `full` – `{string}` – Full version string, such as "0.9.18". - * - `major` – `{number}` – Major version number, such as "0". - * - `minor` – `{number}` – Minor version number, such as "9". - * - `dot` – `{number}` – Dot version number, such as "18". - * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". - */ -var version = { - full: '1.0.7', // all of these placeholder strings will be replaced by grunt's - major: 1, // package task - minor: 0, - dot: 7, - codeName: 'monochromatic-rainbow' -}; - - -function publishExternalAPI(angular){ - extend(angular, { - 'bootstrap': bootstrap, - 'copy': copy, - 'extend': extend, - 'equals': equals, - 'element': jqLite, - 'forEach': forEach, - 'injector': createInjector, - 'noop':noop, - 'bind':bind, - 'toJson': toJson, - 'fromJson': fromJson, - 'identity':identity, - 'isUndefined': isUndefined, - 'isDefined': isDefined, - 'isString': isString, - 'isFunction': isFunction, - 'isObject': isObject, - 'isNumber': isNumber, - 'isElement': isElement, - 'isArray': isArray, - 'version': version, - 'isDate': isDate, - 'lowercase': lowercase, - 'uppercase': uppercase, - 'callbacks': {counter: 0} - }); - - angularModule = setupModuleLoader(window); - try { - angularModule('ngLocale'); - } catch (e) { - angularModule('ngLocale', []).provider('$locale', $LocaleProvider); - } - - angularModule('ng', ['ngLocale'], ['$provide', - function ngModule($provide) { - $provide.provider('$compile', $CompileProvider). - directive({ - a: htmlAnchorDirective, - input: inputDirective, - textarea: inputDirective, - form: formDirective, - script: scriptDirective, - select: selectDirective, - style: styleDirective, - option: optionDirective, - ngBind: ngBindDirective, - ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective, - ngBindTemplate: ngBindTemplateDirective, - ngClass: ngClassDirective, - ngClassEven: ngClassEvenDirective, - ngClassOdd: ngClassOddDirective, - ngCsp: ngCspDirective, - ngCloak: ngCloakDirective, - ngController: ngControllerDirective, - ngForm: ngFormDirective, - ngHide: ngHideDirective, - ngInclude: ngIncludeDirective, - ngInit: ngInitDirective, - ngNonBindable: ngNonBindableDirective, - ngPluralize: ngPluralizeDirective, - ngRepeat: ngRepeatDirective, - ngShow: ngShowDirective, - ngSubmit: ngSubmitDirective, - ngStyle: ngStyleDirective, - ngSwitch: ngSwitchDirective, - ngSwitchWhen: ngSwitchWhenDirective, - ngSwitchDefault: ngSwitchDefaultDirective, - ngOptions: ngOptionsDirective, - ngView: ngViewDirective, - ngTransclude: ngTranscludeDirective, - ngModel: ngModelDirective, - ngList: ngListDirective, - ngChange: ngChangeDirective, - required: requiredDirective, - ngRequired: requiredDirective, - ngValue: ngValueDirective - }). - directive(ngAttributeAliasDirectives). - directive(ngEventDirectives); - $provide.provider({ - $anchorScroll: $AnchorScrollProvider, - $browser: $BrowserProvider, - $cacheFactory: $CacheFactoryProvider, - $controller: $ControllerProvider, - $document: $DocumentProvider, - $exceptionHandler: $ExceptionHandlerProvider, - $filter: $FilterProvider, - $interpolate: $InterpolateProvider, - $http: $HttpProvider, - $httpBackend: $HttpBackendProvider, - $location: $LocationProvider, - $log: $LogProvider, - $parse: $ParseProvider, - $route: $RouteProvider, - $routeParams: $RouteParamsProvider, - $rootScope: $RootScopeProvider, - $q: $QProvider, - $sniffer: $SnifferProvider, - $templateCache: $TemplateCacheProvider, - $timeout: $TimeoutProvider, - $window: $WindowProvider - }); - } - ]); -} - -////////////////////////////////// -//JQLite -////////////////////////////////// - -/** - * @ngdoc function - * @name angular.element - * @function - * - * @description - * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. - * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if - * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite - * implementation (commonly referred to as jqLite). - * - * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded` - * event fired. - * - * jqLite is a tiny, API-compatible subset of jQuery that allows - * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality - * within a very small footprint, so only a subset of the jQuery API - methods, arguments and - * invocation styles - are supported. - * - * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never - * raw DOM references. - * - * ## Angular's jQuery lite provides the following methods: - * - * - [addClass()](http://api.jquery.com/addClass/) - * - [after()](http://api.jquery.com/after/) - * - [append()](http://api.jquery.com/append/) - * - [attr()](http://api.jquery.com/attr/) - * - [bind()](http://api.jquery.com/bind/) - Does not support namespaces - * - [children()](http://api.jquery.com/children/) - Does not support selectors - * - [clone()](http://api.jquery.com/clone/) - * - [contents()](http://api.jquery.com/contents/) - * - [css()](http://api.jquery.com/css/) - * - [data()](http://api.jquery.com/data/) - * - [eq()](http://api.jquery.com/eq/) - * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name - * - [hasClass()](http://api.jquery.com/hasClass/) - * - [html()](http://api.jquery.com/html/) - * - [next()](http://api.jquery.com/next/) - Does not support selectors - * - [parent()](http://api.jquery.com/parent/) - Does not support selectors - * - [prepend()](http://api.jquery.com/prepend/) - * - [prop()](http://api.jquery.com/prop/) - * - [ready()](http://api.jquery.com/ready/) - * - [remove()](http://api.jquery.com/remove/) - * - [removeAttr()](http://api.jquery.com/removeAttr/) - * - [removeClass()](http://api.jquery.com/removeClass/) - * - [removeData()](http://api.jquery.com/removeData/) - * - [replaceWith()](http://api.jquery.com/replaceWith/) - * - [text()](http://api.jquery.com/text/) - * - [toggleClass()](http://api.jquery.com/toggleClass/) - * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers. - * - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces - * - [val()](http://api.jquery.com/val/) - * - [wrap()](http://api.jquery.com/wrap/) - * - * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite: - * - * - `controller(name)` - retrieves the controller of the current element or its parent. By default - * retrieves controller associated with the `ngController` directive. If `name` is provided as - * camelCase directive name, then the controller for this directive will be retrieved (e.g. - * `'ngModel'`). - * - `injector()` - retrieves the injector of the current element or its parent. - * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current - * element or its parent. - * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top - * parent element is reached. - * - * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. - * @returns {Object} jQuery object. - */ - -var jqCache = JQLite.cache = {}, - jqName = JQLite.expando = 'ng-' + new Date().getTime(), - jqId = 1, - addEventListenerFn = (window.document.addEventListener - ? function(element, type, fn) {element.addEventListener(type, fn, false);} - : function(element, type, fn) {element.attachEvent('on' + type, fn);}), - removeEventListenerFn = (window.document.removeEventListener - ? function(element, type, fn) {element.removeEventListener(type, fn, false); } - : function(element, type, fn) {element.detachEvent('on' + type, fn); }); - -function jqNextId() { return ++jqId; } - - -var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; -var MOZ_HACK_REGEXP = /^moz([A-Z])/; - -/** - * Converts snake_case to camelCase. - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize - */ -function camelCase(name) { - return name. - replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }). - replace(MOZ_HACK_REGEXP, 'Moz$1'); -} - -///////////////////////////////////////////// -// jQuery mutation patch -// -// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a -// $destroy event on all DOM nodes being removed. -// -///////////////////////////////////////////// - -function JQLitePatchJQueryRemove(name, dispatchThis) { - var originalJqFn = jQuery.fn[name]; - originalJqFn = originalJqFn.$original || originalJqFn; - removePatch.$original = originalJqFn; - jQuery.fn[name] = removePatch; - - function removePatch() { - var list = [this], - fireEvent = dispatchThis, - set, setIndex, setLength, - element, childIndex, childLength, children, - fns, events; - - while(list.length) { - set = list.shift(); - for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) { - element = jqLite(set[setIndex]); - if (fireEvent) { - element.triggerHandler('$destroy'); - } else { - fireEvent = !fireEvent; - } - for(childIndex = 0, childLength = (children = element.children()).length; - childIndex < childLength; - childIndex++) { - list.push(jQuery(children[childIndex])); - } - } - } - return originalJqFn.apply(this, arguments); - } -} - -///////////////////////////////////////////// -function JQLite(element) { - if (element instanceof JQLite) { - return element; - } - if (!(this instanceof JQLite)) { - if (isString(element) && element.charAt(0) != '<') { - throw Error('selectors not implemented'); - } - return new JQLite(element); - } - - if (isString(element)) { - var div = document.createElement('div'); - // Read about the NoScope elements here: - // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx - div.innerHTML = '
 
' + element; // IE insanity to make NoScope elements work! - div.removeChild(div.firstChild); // remove the superfluous div - JQLiteAddNodes(this, div.childNodes); - this.remove(); // detach the elements from the temporary DOM div. - } else { - JQLiteAddNodes(this, element); - } -} - -function JQLiteClone(element) { - return element.cloneNode(true); -} - -function JQLiteDealoc(element){ - JQLiteRemoveData(element); - for ( var i = 0, children = element.childNodes || []; i < children.length; i++) { - JQLiteDealoc(children[i]); - } -} - -function JQLiteUnbind(element, type, fn) { - var events = JQLiteExpandoStore(element, 'events'), - handle = JQLiteExpandoStore(element, 'handle'); - - if (!handle) return; //no listeners registered - - if (isUndefined(type)) { - forEach(events, function(eventHandler, type) { - removeEventListenerFn(element, type, eventHandler); - delete events[type]; - }); - } else { - if (isUndefined(fn)) { - removeEventListenerFn(element, type, events[type]); - delete events[type]; - } else { - arrayRemove(events[type], fn); - } - } -} - -function JQLiteRemoveData(element) { - var expandoId = element[jqName], - expandoStore = jqCache[expandoId]; - - if (expandoStore) { - if (expandoStore.handle) { - expandoStore.events.$destroy && expandoStore.handle({}, '$destroy'); - JQLiteUnbind(element); - } - delete jqCache[expandoId]; - element[jqName] = undefined; // ie does not allow deletion of attributes on elements. - } -} - -function JQLiteExpandoStore(element, key, value) { - var expandoId = element[jqName], - expandoStore = jqCache[expandoId || -1]; - - if (isDefined(value)) { - if (!expandoStore) { - element[jqName] = expandoId = jqNextId(); - expandoStore = jqCache[expandoId] = {}; - } - expandoStore[key] = value; - } else { - return expandoStore && expandoStore[key]; - } -} - -function JQLiteData(element, key, value) { - var data = JQLiteExpandoStore(element, 'data'), - isSetter = isDefined(value), - keyDefined = !isSetter && isDefined(key), - isSimpleGetter = keyDefined && !isObject(key); - - if (!data && !isSimpleGetter) { - JQLiteExpandoStore(element, 'data', data = {}); - } - - if (isSetter) { - data[key] = value; - } else { - if (keyDefined) { - if (isSimpleGetter) { - // don't create data in this case. - return data && data[key]; - } else { - extend(data, key); - } - } else { - return data; - } - } -} - -function JQLiteHasClass(element, selector) { - return ((" " + element.className + " ").replace(/[\n\t]/g, " "). - indexOf( " " + selector + " " ) > -1); -} - -function JQLiteRemoveClass(element, cssClasses) { - if (cssClasses) { - forEach(cssClasses.split(' '), function(cssClass) { - element.className = trim( - (" " + element.className + " ") - .replace(/[\n\t]/g, " ") - .replace(" " + trim(cssClass) + " ", " ") - ); - }); - } -} - -function JQLiteAddClass(element, cssClasses) { - if (cssClasses) { - forEach(cssClasses.split(' '), function(cssClass) { - if (!JQLiteHasClass(element, cssClass)) { - element.className = trim(element.className + ' ' + trim(cssClass)); - } - }); - } -} - -function JQLiteAddNodes(root, elements) { - if (elements) { - elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements)) - ? elements - : [ elements ]; - for(var i=0; i < elements.length; i++) { - root.push(elements[i]); - } - } -} - -function JQLiteController(element, name) { - return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller'); -} - -function JQLiteInheritedData(element, name, value) { - element = jqLite(element); - - // if element is the document object work with the html element instead - // this makes $(document).scope() possible - if(element[0].nodeType == 9) { - element = element.find('html'); - } - - while (element.length) { - if (value = element.data(name)) return value; - element = element.parent(); - } -} - -////////////////////////////////////////// -// Functions which are declared directly. -////////////////////////////////////////// -var JQLitePrototype = JQLite.prototype = { - ready: function(fn) { - var fired = false; - - function trigger() { - if (fired) return; - fired = true; - fn(); - } - - this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9 - // we can not use jqLite since we are not done loading and jQuery could be loaded later. - JQLite(window).bind('load', trigger); // fallback to window.onload for others - }, - toString: function() { - var value = []; - forEach(this, function(e){ value.push('' + e);}); - return '[' + value.join(', ') + ']'; - }, - - eq: function(index) { - return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); - }, - - length: 0, - push: push, - sort: [].sort, - splice: [].splice -}; - -////////////////////////////////////////// -// Functions iterating getter/setters. -// these functions return self on setter and -// value on get. -////////////////////////////////////////// -var BOOLEAN_ATTR = {}; -forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) { - BOOLEAN_ATTR[lowercase(value)] = value; -}); -var BOOLEAN_ELEMENTS = {}; -forEach('input,select,option,textarea,button,form'.split(','), function(value) { - BOOLEAN_ELEMENTS[uppercase(value)] = true; -}); - -function getBooleanAttrName(element, name) { - // check dom last since we will most likely fail on name - var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; - - // booleanAttr is here twice to minimize DOM access - return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr; -} - -forEach({ - data: JQLiteData, - inheritedData: JQLiteInheritedData, - - scope: function(element) { - return JQLiteInheritedData(element, '$scope'); - }, - - controller: JQLiteController , - - injector: function(element) { - return JQLiteInheritedData(element, '$injector'); - }, - - removeAttr: function(element,name) { - element.removeAttribute(name); - }, - - hasClass: JQLiteHasClass, - - css: function(element, name, value) { - name = camelCase(name); - - if (isDefined(value)) { - element.style[name] = value; - } else { - var val; - - if (msie <= 8) { - // this is some IE specific weirdness that jQuery 1.6.4 does not sure why - val = element.currentStyle && element.currentStyle[name]; - if (val === '') val = 'auto'; - } - - val = val || element.style[name]; - - if (msie <= 8) { - // jquery weirdness :-/ - val = (val === '') ? undefined : val; - } - - return val; - } - }, - - attr: function(element, name, value){ - var lowercasedName = lowercase(name); - if (BOOLEAN_ATTR[lowercasedName]) { - if (isDefined(value)) { - if (!!value) { - element[name] = true; - element.setAttribute(name, lowercasedName); - } else { - element[name] = false; - element.removeAttribute(lowercasedName); - } - } else { - return (element[name] || - (element.attributes.getNamedItem(name)|| noop).specified) - ? lowercasedName - : undefined; - } - } else if (isDefined(value)) { - element.setAttribute(name, value); - } else if (element.getAttribute) { - // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code - // some elements (e.g. Document) don't have get attribute, so return undefined - var ret = element.getAttribute(name, 2); - // normalize non-existing attributes to undefined (as jQuery) - return ret === null ? undefined : ret; - } - }, - - prop: function(element, name, value) { - if (isDefined(value)) { - element[name] = value; - } else { - return element[name]; - } - }, - - text: extend((msie < 9) - ? function(element, value) { - if (element.nodeType == 1 /** Element */) { - if (isUndefined(value)) - return element.innerText; - element.innerText = value; - } else { - if (isUndefined(value)) - return element.nodeValue; - element.nodeValue = value; - } - } - : function(element, value) { - if (isUndefined(value)) { - return element.textContent; - } - element.textContent = value; - }, {$dv:''}), - - val: function(element, value) { - if (isUndefined(value)) { - return element.value; - } - element.value = value; - }, - - html: function(element, value) { - if (isUndefined(value)) { - return element.innerHTML; - } - for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) { - JQLiteDealoc(childNodes[i]); - } - element.innerHTML = value; - } -}, function(fn, name){ - /** - * Properties: writes return selection, reads return first value - */ - JQLite.prototype[name] = function(arg1, arg2) { - var i, key; - - // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it - // in a way that survives minification. - if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) { - if (isObject(arg1)) { - - // we are a write, but the object properties are the key/values - for(i=0; i < this.length; i++) { - if (fn === JQLiteData) { - // data() takes the whole object in jQuery - fn(this[i], arg1); - } else { - for (key in arg1) { - fn(this[i], key, arg1[key]); - } - } - } - // return self for chaining - return this; - } else { - // we are a read, so read the first child. - if (this.length) - return fn(this[0], arg1, arg2); - } - } else { - // we are a write, so apply to all children - for(i=0; i < this.length; i++) { - fn(this[i], arg1, arg2); - } - // return self for chaining - return this; - } - return fn.$dv; - }; -}); - -function createEventHandler(element, events) { - var eventHandler = function (event, type) { - if (!event.preventDefault) { - event.preventDefault = function() { - event.returnValue = false; //ie - }; - } - - if (!event.stopPropagation) { - event.stopPropagation = function() { - event.cancelBubble = true; //ie - }; - } - - if (!event.target) { - event.target = event.srcElement || document; - } - - if (isUndefined(event.defaultPrevented)) { - var prevent = event.preventDefault; - event.preventDefault = function() { - event.defaultPrevented = true; - prevent.call(event); - }; - event.defaultPrevented = false; - } - - event.isDefaultPrevented = function() { - return event.defaultPrevented; - }; - - forEach(events[type || event.type], function(fn) { - fn.call(element, event); - }); - - // Remove monkey-patched methods (IE), - // as they would cause memory leaks in IE8. - if (msie <= 8) { - // IE7/8 does not allow to delete property on native object - event.preventDefault = null; - event.stopPropagation = null; - event.isDefaultPrevented = null; - } else { - // It shouldn't affect normal browsers (native methods are defined on prototype). - delete event.preventDefault; - delete event.stopPropagation; - delete event.isDefaultPrevented; - } - }; - eventHandler.elem = element; - return eventHandler; -} - -////////////////////////////////////////// -// Functions iterating traversal. -// These functions chain results into a single -// selector. -////////////////////////////////////////// -forEach({ - removeData: JQLiteRemoveData, - - dealoc: JQLiteDealoc, - - bind: function bindFn(element, type, fn){ - var events = JQLiteExpandoStore(element, 'events'), - handle = JQLiteExpandoStore(element, 'handle'); - - if (!events) JQLiteExpandoStore(element, 'events', events = {}); - if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events)); - - forEach(type.split(' '), function(type){ - var eventFns = events[type]; - - if (!eventFns) { - if (type == 'mouseenter' || type == 'mouseleave') { - var contains = document.body.contains || document.body.compareDocumentPosition ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - events[type] = []; - - // Refer to jQuery's implementation of mouseenter & mouseleave - // Read about mouseenter and mouseleave: - // http://www.quirksmode.org/js/events_mouse.html#link8 - var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"} - bindFn(element, eventmap[type], function(event) { - var ret, target = this, related = event.relatedTarget; - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !contains(target, related)) ){ - handle(event, type); - } - - }); - - } else { - addEventListenerFn(element, type, handle); - events[type] = []; - } - eventFns = events[type] - } - eventFns.push(fn); - }); - }, - - unbind: JQLiteUnbind, - - replaceWith: function(element, replaceNode) { - var index, parent = element.parentNode; - JQLiteDealoc(element); - forEach(new JQLite(replaceNode), function(node){ - if (index) { - parent.insertBefore(node, index.nextSibling); - } else { - parent.replaceChild(node, element); - } - index = node; - }); - }, - - children: function(element) { - var children = []; - forEach(element.childNodes, function(element){ - if (element.nodeType === 1) - children.push(element); - }); - return children; - }, - - contents: function(element) { - return element.childNodes || []; - }, - - append: function(element, node) { - forEach(new JQLite(node), function(child){ - if (element.nodeType === 1) - element.appendChild(child); - }); - }, - - prepend: function(element, node) { - if (element.nodeType === 1) { - var index = element.firstChild; - forEach(new JQLite(node), function(child){ - if (index) { - element.insertBefore(child, index); - } else { - element.appendChild(child); - index = child; - } - }); - } - }, - - wrap: function(element, wrapNode) { - wrapNode = jqLite(wrapNode)[0]; - var parent = element.parentNode; - if (parent) { - parent.replaceChild(wrapNode, element); - } - wrapNode.appendChild(element); - }, - - remove: function(element) { - JQLiteDealoc(element); - var parent = element.parentNode; - if (parent) parent.removeChild(element); - }, - - after: function(element, newElement) { - var index = element, parent = element.parentNode; - forEach(new JQLite(newElement), function(node){ - parent.insertBefore(node, index.nextSibling); - index = node; - }); - }, - - addClass: JQLiteAddClass, - removeClass: JQLiteRemoveClass, - - toggleClass: function(element, selector, condition) { - if (isUndefined(condition)) { - condition = !JQLiteHasClass(element, selector); - } - (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector); - }, - - parent: function(element) { - var parent = element.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - - next: function(element) { - if (element.nextElementSibling) { - return element.nextElementSibling; - } - - // IE8 doesn't have nextElementSibling - var elm = element.nextSibling; - while (elm != null && elm.nodeType !== 1) { - elm = elm.nextSibling; - } - return elm; - }, - - find: function(element, selector) { - return element.getElementsByTagName(selector); - }, - - clone: JQLiteClone, - - triggerHandler: function(element, eventName) { - var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName]; - - forEach(eventFns, function(fn) { - fn.call(element, null); - }); - } -}, function(fn, name){ - /** - * chaining functions - */ - JQLite.prototype[name] = function(arg1, arg2) { - var value; - for(var i=0; i < this.length; i++) { - if (value == undefined) { - value = fn(this[i], arg1, arg2); - if (value !== undefined) { - // any function which returns a value needs to be wrapped - value = jqLite(value); - } - } else { - JQLiteAddNodes(value, fn(this[i], arg1, arg2)); - } - } - return value == undefined ? this : value; - }; -}); - -/** - * Computes a hash of an 'obj'. - * Hash of a: - * string is string - * number is number as string - * object is either result of calling $$hashKey function on the object or uniquely generated id, - * that is also assigned to the $$hashKey property of the object. - * - * @param obj - * @returns {string} hash string such that the same input will have the same hash string. - * The resulting string key is in 'type:hashKey' format. - */ -function hashKey(obj) { - var objType = typeof obj, - key; - - if (objType == 'object' && obj !== null) { - if (typeof (key = obj.$$hashKey) == 'function') { - // must invoke on object to keep the right this - key = obj.$$hashKey(); - } else if (key === undefined) { - key = obj.$$hashKey = nextUid(); - } - } else { - key = obj; - } - - return objType + ':' + key; -} - -/** - * HashMap which can use objects as keys - */ -function HashMap(array){ - forEach(array, this.put, this); -} -HashMap.prototype = { - /** - * Store key value pair - * @param key key to store can be any type - * @param value value to store can be any type - */ - put: function(key, value) { - this[hashKey(key)] = value; - }, - - /** - * @param key - * @returns the value for the key - */ - get: function(key) { - return this[hashKey(key)]; - }, - - /** - * Remove the key/value pair - * @param key - */ - remove: function(key) { - var value = this[key = hashKey(key)]; - delete this[key]; - return value; - } -}; - -/** - * A map where multiple values can be added to the same key such that they form a queue. - * @returns {HashQueueMap} - */ -function HashQueueMap() {} -HashQueueMap.prototype = { - /** - * Same as array push, but using an array as the value for the hash - */ - push: function(key, value) { - var array = this[key = hashKey(key)]; - if (!array) { - this[key] = [value]; - } else { - array.push(value); - } - }, - - /** - * Same as array shift, but using an array as the value for the hash - */ - shift: function(key) { - var array = this[key = hashKey(key)]; - if (array) { - if (array.length == 1) { - delete this[key]; - return array[0]; - } else { - return array.shift(); - } - } - }, - - /** - * return the first item without deleting it - */ - peek: function(key) { - var array = this[hashKey(key)]; - if (array) { - return array[0]; - } - } -}; - -/** - * @ngdoc function - * @name angular.injector - * @function - * - * @description - * Creates an injector function that can be used for retrieving services as well as for - * dependency injection (see {@link guide/di dependency injection}). - * - - * @param {Array.} modules A list of module functions or their aliases. See - * {@link angular.module}. The `ng` module must be explicitly added. - * @returns {function()} Injector function. See {@link AUTO.$injector $injector}. - * - * @example - * Typical usage - *
- *   // create an injector
- *   var $injector = angular.injector(['ng']);
- *
- *   // use the injector to kick off your application
- *   // use the type inference to auto inject arguments, or use implicit injection
- *   $injector.invoke(function($rootScope, $compile, $document){
- *     $compile($document)($rootScope);
- *     $rootScope.$digest();
- *   });
- * 
- */ - - -/** - * @ngdoc overview - * @name AUTO - * @description - * - * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}. - */ - -var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; -var FN_ARG_SPLIT = /,/; -var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; -var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; -function annotate(fn) { - var $inject, - fnText, - argDecl, - last; - - if (typeof fn == 'function') { - if (!($inject = fn.$inject)) { - $inject = []; - fnText = fn.toString().replace(STRIP_COMMENTS, ''); - argDecl = fnText.match(FN_ARGS); - forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ - arg.replace(FN_ARG, function(all, underscore, name){ - $inject.push(name); - }); - }); - fn.$inject = $inject; - } - } else if (isArray(fn)) { - last = fn.length - 1; - assertArgFn(fn[last], 'fn'); - $inject = fn.slice(0, last); - } else { - assertArgFn(fn, 'fn', true); - } - return $inject; -} - -/////////////////////////////////////// - -/** - * @ngdoc object - * @name AUTO.$injector - * @function - * - * @description - * - * `$injector` is used to retrieve object instances as defined by - * {@link AUTO.$provide provider}, instantiate types, invoke methods, - * and load modules. - * - * The following always holds true: - * - *
- *   var $injector = angular.injector();
- *   expect($injector.get('$injector')).toBe($injector);
- *   expect($injector.invoke(function($injector){
- *     return $injector;
- *   }).toBe($injector);
- * 
- * - * # Injection Function Annotation - * - * JavaScript does not have annotations, and annotations are needed for dependency injection. The - * following are all valid ways of annotating function with injection arguments and are equivalent. - * - *
- *   // inferred (only works if code not minified/obfuscated)
- *   $injector.invoke(function(serviceA){});
- *
- *   // annotated
- *   function explicit(serviceA) {};
- *   explicit.$inject = ['serviceA'];
- *   $injector.invoke(explicit);
- *
- *   // inline
- *   $injector.invoke(['serviceA', function(serviceA){}]);
- * 
- * - * ## Inference - * - * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be - * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation - * tools since these tools change the argument names. - * - * ## `$inject` Annotation - * By adding a `$inject` property onto a function the injection parameters can be specified. - * - * ## Inline - * As an array of injection names, where the last item in the array is the function to call. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#get - * @methodOf AUTO.$injector - * - * @description - * Return an instance of the service. - * - * @param {string} name The name of the instance to retrieve. - * @return {*} The instance. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#invoke - * @methodOf AUTO.$injector - * - * @description - * Invoke the method and supply the method arguments from the `$injector`. - * - * @param {!function} fn The function to invoke. The function arguments come form the function annotation. - * @param {Object=} self The `this` for the invoked method. - * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before - * the `$injector` is consulted. - * @returns {*} the value returned by the invoked `fn` function. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#instantiate - * @methodOf AUTO.$injector - * @description - * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies - * all of the arguments to the constructor function as specified by the constructor annotation. - * - * @param {function} Type Annotated constructor function. - * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before - * the `$injector` is consulted. - * @returns {Object} new instance of `Type`. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#annotate - * @methodOf AUTO.$injector - * - * @description - * Returns an array of service names which the function is requesting for injection. This API is used by the injector - * to determine which services need to be injected into the function when the function is invoked. There are three - * ways in which the function can be annotated with the needed dependencies. - * - * # Argument names - * - * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting - * the function into a string using `toString()` method and extracting the argument names. - *
- *   // Given
- *   function MyController($scope, $route) {
- *     // ...
- *   }
- *
- *   // Then
- *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * 
- * - * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies - * are supported. - * - * # The `$inject` property - * - * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of - * services to be injected into the function. - *
- *   // Given
- *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
- *     // ...
- *   }
- *   // Define function dependencies
- *   MyController.$inject = ['$scope', '$route'];
- *
- *   // Then
- *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * 
- * - * # The array notation - * - * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very - * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives - * minification is a better choice: - * - *
- *   // We wish to write this (not minification / obfuscation safe)
- *   injector.invoke(function($compile, $rootScope) {
- *     // ...
- *   });
- *
- *   // We are forced to write break inlining
- *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
- *     // ...
- *   };
- *   tmpFn.$inject = ['$compile', '$rootScope'];
- *   injector.invoke(tmpFn);
- *
- *   // To better support inline function the inline annotation is supported
- *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
- *     // ...
- *   }]);
- *
- *   // Therefore
- *   expect(injector.annotate(
- *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
- *    ).toEqual(['$compile', '$rootScope']);
- * 
- * - * @param {function|Array.} fn Function for which dependent service names need to be retrieved as described - * above. - * - * @returns {Array.} The names of the services which the function requires. - */ - - - - -/** - * @ngdoc object - * @name AUTO.$provide - * - * @description - * - * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance. - * The providers share the same name as the instance they create with `Provider` suffixed to them. - * - * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of - * a service. The Provider can have additional methods which would allow for configuration of the provider. - * - *
- *   function GreetProvider() {
- *     var salutation = 'Hello';
- *
- *     this.salutation = function(text) {
- *       salutation = text;
- *     };
- *
- *     this.$get = function() {
- *       return function (name) {
- *         return salutation + ' ' + name + '!';
- *       };
- *     };
- *   }
- *
- *   describe('Greeter', function(){
- *
- *     beforeEach(module(function($provide) {
- *       $provide.provider('greet', GreetProvider);
- *     }));
- *
- *     it('should greet', inject(function(greet) {
- *       expect(greet('angular')).toEqual('Hello angular!');
- *     }));
- *
- *     it('should allow configuration of salutation', function() {
- *       module(function(greetProvider) {
- *         greetProvider.salutation('Ahoj');
- *       });
- *       inject(function(greet) {
- *         expect(greet('angular')).toEqual('Ahoj angular!');
- *       });
- *     });
- * 
- */ - -/** - * @ngdoc method - * @name AUTO.$provide#provider - * @methodOf AUTO.$provide - * @description - * - * Register a provider for a service. The providers can be retrieved and can have additional configuration methods. - * - * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key. - * @param {(Object|function())} provider If the provider is: - * - * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using - * {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created. - * - `Constructor`: a new instance of the provider will be created using - * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`. - * - * @returns {Object} registered provider instance - */ - -/** - * @ngdoc method - * @name AUTO.$provide#factory - * @methodOf AUTO.$provide - * @description - * - * A short hand for configuring services if only `$get` method is required. - * - * @param {string} name The name of the instance. - * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for - * `$provide.provider(name, {$get: $getFn})`. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#service - * @methodOf AUTO.$provide - * @description - * - * A short hand for registering service of given class. - * - * @param {string} name The name of the instance. - * @param {Function} constructor A class (constructor function) that will be instantiated. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#value - * @methodOf AUTO.$provide - * @description - * - * A short hand for configuring services if the `$get` method is a constant. - * - * @param {string} name The name of the instance. - * @param {*} value The value. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#constant - * @methodOf AUTO.$provide - * @description - * - * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected - * into configuration function (other modules) and it is not interceptable by - * {@link AUTO.$provide#decorator decorator}. - * - * @param {string} name The name of the constant. - * @param {*} value The constant value. - * @returns {Object} registered instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#decorator - * @methodOf AUTO.$provide - * @description - * - * Decoration of service, allows the decorator to intercept the service instance creation. The - * returned instance may be the original instance, or a new instance which delegates to the - * original instance. - * - * @param {string} name The name of the service to decorate. - * @param {function()} decorator This function will be invoked when the service needs to be - * instantiated. The function is called using the {@link AUTO.$injector#invoke - * injector.invoke} method and is therefore fully injectable. Local injection arguments: - * - * * `$delegate` - The original service instance, which can be monkey patched, configured, - * decorated or delegated to. - */ - - -function createInjector(modulesToLoad) { - var INSTANTIATING = {}, - providerSuffix = 'Provider', - path = [], - loadedModules = new HashMap(), - providerCache = { - $provide: { - provider: supportObject(provider), - factory: supportObject(factory), - service: supportObject(service), - value: supportObject(value), - constant: supportObject(constant), - decorator: decorator - } - }, - providerInjector = createInternalInjector(providerCache, function() { - throw Error("Unknown provider: " + path.join(' <- ')); - }), - instanceCache = {}, - instanceInjector = (instanceCache.$injector = - createInternalInjector(instanceCache, function(servicename) { - var provider = providerInjector.get(servicename + providerSuffix); - return instanceInjector.invoke(provider.$get, provider); - })); - - - forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); - - return instanceInjector; - - //////////////////////////////////// - // $provider - //////////////////////////////////// - - function supportObject(delegate) { - return function(key, value) { - if (isObject(key)) { - forEach(key, reverseParams(delegate)); - } else { - return delegate(key, value); - } - } - } - - function provider(name, provider_) { - if (isFunction(provider_) || isArray(provider_)) { - provider_ = providerInjector.instantiate(provider_); - } - if (!provider_.$get) { - throw Error('Provider ' + name + ' must define $get factory method.'); - } - return providerCache[name + providerSuffix] = provider_; - } - - function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } - - function service(name, constructor) { - return factory(name, ['$injector', function($injector) { - return $injector.instantiate(constructor); - }]); - } - - function value(name, value) { return factory(name, valueFn(value)); } - - function constant(name, value) { - providerCache[name] = value; - instanceCache[name] = value; - } - - function decorator(serviceName, decorFn) { - var origProvider = providerInjector.get(serviceName + providerSuffix), - orig$get = origProvider.$get; - - origProvider.$get = function() { - var origInstance = instanceInjector.invoke(orig$get, origProvider); - return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); - }; - } - - //////////////////////////////////// - // Module Loading - //////////////////////////////////// - function loadModules(modulesToLoad){ - var runBlocks = []; - forEach(modulesToLoad, function(module) { - if (loadedModules.get(module)) return; - loadedModules.put(module, true); - if (isString(module)) { - var moduleFn = angularModule(module); - runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); - - try { - for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { - var invokeArgs = invokeQueue[i], - provider = invokeArgs[0] == '$injector' - ? providerInjector - : providerInjector.get(invokeArgs[0]); - - provider[invokeArgs[1]].apply(provider, invokeArgs[2]); - } - } catch (e) { - if (e.message) e.message += ' from ' + module; - throw e; - } - } else if (isFunction(module)) { - try { - runBlocks.push(providerInjector.invoke(module)); - } catch (e) { - if (e.message) e.message += ' from ' + module; - throw e; - } - } else if (isArray(module)) { - try { - runBlocks.push(providerInjector.invoke(module)); - } catch (e) { - if (e.message) e.message += ' from ' + String(module[module.length - 1]); - throw e; - } - } else { - assertArgFn(module, 'module'); - } - }); - return runBlocks; - } - - //////////////////////////////////// - // internal Injector - //////////////////////////////////// - - function createInternalInjector(cache, factory) { - - function getService(serviceName) { - if (typeof serviceName !== 'string') { - throw Error('Service name expected'); - } - if (cache.hasOwnProperty(serviceName)) { - if (cache[serviceName] === INSTANTIATING) { - throw Error('Circular dependency: ' + path.join(' <- ')); - } - return cache[serviceName]; - } else { - try { - path.unshift(serviceName); - cache[serviceName] = INSTANTIATING; - return cache[serviceName] = factory(serviceName); - } finally { - path.shift(); - } - } - } - - function invoke(fn, self, locals){ - var args = [], - $inject = annotate(fn), - length, i, - key; - - for(i = 0, length = $inject.length; i < length; i++) { - key = $inject[i]; - args.push( - locals && locals.hasOwnProperty(key) - ? locals[key] - : getService(key) - ); - } - if (!fn.$inject) { - // this means that we must be an array. - fn = fn[length]; - } - - - // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke - switch (self ? -1 : args.length) { - case 0: return fn(); - case 1: return fn(args[0]); - case 2: return fn(args[0], args[1]); - case 3: return fn(args[0], args[1], args[2]); - case 4: return fn(args[0], args[1], args[2], args[3]); - case 5: return fn(args[0], args[1], args[2], args[3], args[4]); - case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); - default: return fn.apply(self, args); - } - } - - function instantiate(Type, locals) { - var Constructor = function() {}, - instance, returnedValue; - - // Check if Type is annotated and use just the given function at n-1 as parameter - // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); - Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype; - instance = new Constructor(); - returnedValue = invoke(Type, instance, locals); - - return isObject(returnedValue) ? returnedValue : instance; - } - - return { - invoke: invoke, - instantiate: instantiate, - get: getService, - annotate: annotate - }; - } -} - -/** - * @ngdoc function - * @name ng.$anchorScroll - * @requires $window - * @requires $location - * @requires $rootScope - * - * @description - * When called, it checks current value of `$location.hash()` and scroll to related element, - * according to rules specified in - * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}. - * - * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor. - * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`. - */ -function $AnchorScrollProvider() { - - var autoScrollingEnabled = true; - - this.disableAutoScrolling = function() { - autoScrollingEnabled = false; - }; - - this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { - var document = $window.document; - - // helper function to get first anchor from a NodeList - // can't use filter.filter, as it accepts only instances of Array - // and IE can't convert NodeList to an array using [].slice - // TODO(vojta): use filter if we change it to accept lists as well - function getFirstAnchor(list) { - var result = null; - forEach(list, function(element) { - if (!result && lowercase(element.nodeName) === 'a') result = element; - }); - return result; - } - - function scroll() { - var hash = $location.hash(), elm; - - // empty hash, scroll to the top of the page - if (!hash) $window.scrollTo(0, 0); - - // element with given id - else if ((elm = document.getElementById(hash))) elm.scrollIntoView(); - - // first anchor with given name :-D - else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView(); - - // no element and hash == 'top', scroll to the top of the page - else if (hash === 'top') $window.scrollTo(0, 0); - } - - // does not scroll when user clicks on anchor link that is currently on - // (no url change, no $location.hash() change), browser native does scroll - if (autoScrollingEnabled) { - $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, - function autoScrollWatchAction() { - $rootScope.$evalAsync(scroll); - }); - } - - return scroll; - }]; -} - -/** - * ! This is a private undocumented service ! - * - * @name ng.$browser - * @requires $log - * @description - * This object has two goals: - * - * - hide all the global state in the browser caused by the window object - * - abstract away all the browser specific features and inconsistencies - * - * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` - * service, which can be used for convenient testing of the application without the interaction with - * the real browser apis. - */ -/** - * @param {object} window The global window object. - * @param {object} document jQuery wrapped document. - * @param {function()} XHR XMLHttpRequest constructor. - * @param {object} $log console.log or an object with the same interface. - * @param {object} $sniffer $sniffer service - */ -function Browser(window, document, $log, $sniffer) { - var self = this, - rawDocument = document[0], - location = window.location, - history = window.history, - setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout, - pendingDeferIds = {}; - - self.isMock = false; - - var outstandingRequestCount = 0; - var outstandingRequestCallbacks = []; - - // TODO(vojta): remove this temporary api - self.$$completeOutstandingRequest = completeOutstandingRequest; - self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; - - /** - * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` - * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. - */ - function completeOutstandingRequest(fn) { - try { - fn.apply(null, sliceArgs(arguments, 1)); - } finally { - outstandingRequestCount--; - if (outstandingRequestCount === 0) { - while(outstandingRequestCallbacks.length) { - try { - outstandingRequestCallbacks.pop()(); - } catch (e) { - $log.error(e); - } - } - } - } - } - - /** - * @private - * Note: this method is used only by scenario runner - * TODO(vojta): prefix this method with $$ ? - * @param {function()} callback Function that will be called when no outstanding request - */ - self.notifyWhenNoOutstandingRequests = function(callback) { - // force browser to execute all pollFns - this is needed so that cookies and other pollers fire - // at some deterministic time in respect to the test runner's actions. Leaving things up to the - // regular poller would result in flaky tests. - forEach(pollFns, function(pollFn){ pollFn(); }); - - if (outstandingRequestCount === 0) { - callback(); - } else { - outstandingRequestCallbacks.push(callback); - } - }; - - ////////////////////////////////////////////////////////////// - // Poll Watcher API - ////////////////////////////////////////////////////////////// - var pollFns = [], - pollTimeout; - - /** - * @name ng.$browser#addPollFn - * @methodOf ng.$browser - * - * @param {function()} fn Poll function to add - * - * @description - * Adds a function to the list of functions that poller periodically executes, - * and starts polling if not started yet. - * - * @returns {function()} the added function - */ - self.addPollFn = function(fn) { - if (isUndefined(pollTimeout)) startPoller(100, setTimeout); - pollFns.push(fn); - return fn; - }; - - /** - * @param {number} interval How often should browser call poll functions (ms) - * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. - * - * @description - * Configures the poller to run in the specified intervals, using the specified - * setTimeout fn and kicks it off. - */ - function startPoller(interval, setTimeout) { - (function check() { - forEach(pollFns, function(pollFn){ pollFn(); }); - pollTimeout = setTimeout(check, interval); - })(); - } - - ////////////////////////////////////////////////////////////// - // URL API - ////////////////////////////////////////////////////////////// - - var lastBrowserUrl = location.href, - baseElement = document.find('base'); - - /** - * @name ng.$browser#url - * @methodOf ng.$browser - * - * @description - * GETTER: - * Without any argument, this method just returns current value of location.href. - * - * SETTER: - * With at least one argument, this method sets url to new value. - * If html5 history api supported, pushState/replaceState is used, otherwise - * location.href/location.replace is used. - * Returns its own instance to allow chaining - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to change url. - * - * @param {string} url New url (when used as setter) - * @param {boolean=} replace Should new url replace current history record ? - */ - self.url = function(url, replace) { - // setter - if (url) { - if (lastBrowserUrl == url) return; - lastBrowserUrl = url; - if ($sniffer.history) { - if (replace) history.replaceState(null, '', url); - else { - history.pushState(null, '', url); - // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462 - baseElement.attr('href', baseElement.attr('href')); - } - } else { - if (replace) location.replace(url); - else location.href = url; - } - return self; - // getter - } else { - // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 - return location.href.replace(/%27/g,"'"); - } - }; - - var urlChangeListeners = [], - urlChangeInit = false; - - function fireUrlChange() { - if (lastBrowserUrl == self.url()) return; - - lastBrowserUrl = self.url(); - forEach(urlChangeListeners, function(listener) { - listener(self.url()); - }); - } - - /** - * @name ng.$browser#onUrlChange - * @methodOf ng.$browser - * @TODO(vojta): refactor to use node's syntax for events - * - * @description - * Register callback function that will be called, when url changes. - * - * It's only called when the url is changed by outside of angular: - * - user types different url into address bar - * - user clicks on history (forward/back) button - * - user clicks on a link - * - * It's not called when url is changed by $browser.url() method - * - * The listener gets called with new url as parameter. - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to monitor url changes in angular apps. - * - * @param {function(string)} listener Listener function to be called when url changes. - * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. - */ - self.onUrlChange = function(callback) { - if (!urlChangeInit) { - // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) - // don't fire popstate when user change the address bar and don't fire hashchange when url - // changed by push/replaceState - - // html5 history api - popstate event - if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange); - // hashchange event - if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange); - // polling - else self.addPollFn(fireUrlChange); - - urlChangeInit = true; - } - - urlChangeListeners.push(callback); - return callback; - }; - - ////////////////////////////////////////////////////////////// - // Misc API - ////////////////////////////////////////////////////////////// - - /** - * Returns current - * (always relative - without domain) - * - * @returns {string=} - */ - self.baseHref = function() { - var href = baseElement.attr('href'); - return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : ''; - }; - - ////////////////////////////////////////////////////////////// - // Cookies API - ////////////////////////////////////////////////////////////// - var lastCookies = {}; - var lastCookieString = ''; - var cookiePath = self.baseHref(); - - /** - * @name ng.$browser#cookies - * @methodOf ng.$browser - * - * @param {string=} name Cookie name - * @param {string=} value Cokkie value - * - * @description - * The cookies method provides a 'private' low level access to browser cookies. - * It is not meant to be used directly, use the $cookie service instead. - * - * The return values vary depending on the arguments that the method was called with as follows: - *
    - *
  • cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it
  • - *
  • cookies(name, value) -> set name to value, if value is undefined delete the cookie
  • - *
  • cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)
  • - *
- * - * @returns {Object} Hash of all cookies (if called without any parameter) - */ - self.cookies = function(name, value) { - var cookieLength, cookieArray, cookie, i, index; - - if (name) { - if (value === undefined) { - rawDocument.cookie = escape(name) + "=;path=" + cookiePath + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (isString(value)) { - cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1; - - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+ - cookieLength + " > 4096 bytes)!"); - } - } - } - } else { - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - var name = unescape(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (lastCookies[name] === undefined) { - lastCookies[name] = unescape(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - } - }; - - - /** - * @name ng.$browser#defer - * @methodOf ng.$browser - * @param {function()} fn A function, who's execution should be defered. - * @param {number=} [delay=0] of milliseconds to defer the function execution. - * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. - * - * @description - * Executes a fn asynchroniously via `setTimeout(fn, delay)`. - * - * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using - * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed - * via `$browser.defer.flush()`. - * - */ - self.defer = function(fn, delay) { - var timeoutId; - outstandingRequestCount++; - timeoutId = setTimeout(function() { - delete pendingDeferIds[timeoutId]; - completeOutstandingRequest(fn); - }, delay || 0); - pendingDeferIds[timeoutId] = true; - return timeoutId; - }; - - - /** - * @name ng.$browser#defer.cancel - * @methodOf ng.$browser.defer - * - * @description - * Cancels a defered task identified with `deferId`. - * - * @param {*} deferId Token returned by the `$browser.defer` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled. - */ - self.defer.cancel = function(deferId) { - if (pendingDeferIds[deferId]) { - delete pendingDeferIds[deferId]; - clearTimeout(deferId); - completeOutstandingRequest(noop); - return true; - } - return false; - }; - -} - -function $BrowserProvider(){ - this.$get = ['$window', '$log', '$sniffer', '$document', - function( $window, $log, $sniffer, $document){ - return new Browser($window, $document, $log, $sniffer); - }]; -} - -/** - * @ngdoc object - * @name ng.$cacheFactory - * - * @description - * Factory that constructs cache objects. - * - * - * @param {string} cacheId Name or id of the newly created cache. - * @param {object=} options Options object that specifies the cache behavior. Properties: - * - * - `{number=}` `capacity` — turns the cache into LRU cache. - * - * @returns {object} Newly created cache object with the following set of methods: - * - * - `{object}` `info()` — Returns id, size, and options of cache. - * - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache. - * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. - * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. - * - `{void}` `removeAll()` — Removes all cached values. - * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. - * - */ -function $CacheFactoryProvider() { - - this.$get = function() { - var caches = {}; - - function cacheFactory(cacheId, options) { - if (cacheId in caches) { - throw Error('cacheId ' + cacheId + ' taken'); - } - - var size = 0, - stats = extend({}, options, {id: cacheId}), - data = {}, - capacity = (options && options.capacity) || Number.MAX_VALUE, - lruHash = {}, - freshEnd = null, - staleEnd = null; - - return caches[cacheId] = { - - put: function(key, value) { - var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); - - refresh(lruEntry); - - if (isUndefined(value)) return; - if (!(key in data)) size++; - data[key] = value; - - if (size > capacity) { - this.remove(staleEnd.key); - } - }, - - - get: function(key) { - var lruEntry = lruHash[key]; - - if (!lruEntry) return; - - refresh(lruEntry); - - return data[key]; - }, - - - remove: function(key) { - var lruEntry = lruHash[key]; - - if (!lruEntry) return; - - if (lruEntry == freshEnd) freshEnd = lruEntry.p; - if (lruEntry == staleEnd) staleEnd = lruEntry.n; - link(lruEntry.n,lruEntry.p); - - delete lruHash[key]; - delete data[key]; - size--; - }, - - - removeAll: function() { - data = {}; - size = 0; - lruHash = {}; - freshEnd = staleEnd = null; - }, - - - destroy: function() { - data = null; - stats = null; - lruHash = null; - delete caches[cacheId]; - }, - - - info: function() { - return extend({}, stats, {size: size}); - } - }; - - - /** - * makes the `entry` the freshEnd of the LRU linked list - */ - function refresh(entry) { - if (entry != freshEnd) { - if (!staleEnd) { - staleEnd = entry; - } else if (staleEnd == entry) { - staleEnd = entry.n; - } - - link(entry.n, entry.p); - link(entry, freshEnd); - freshEnd = entry; - freshEnd.n = null; - } - } - - - /** - * bidirectionally links two entries of the LRU linked list - */ - function link(nextEntry, prevEntry) { - if (nextEntry != prevEntry) { - if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify - if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify - } - } - } - - - cacheFactory.info = function() { - var info = {}; - forEach(caches, function(cache, cacheId) { - info[cacheId] = cache.info(); - }); - return info; - }; - - - cacheFactory.get = function(cacheId) { - return caches[cacheId]; - }; - - - return cacheFactory; - }; -} - -/** - * @ngdoc object - * @name ng.$templateCache - * - * @description - * Cache used for storing html templates. - * - * See {@link ng.$cacheFactory $cacheFactory}. - * - */ -function $TemplateCacheProvider() { - this.$get = ['$cacheFactory', function($cacheFactory) { - return $cacheFactory('templates'); - }]; -} - -/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! - * - * DOM-related variables: - * - * - "node" - DOM Node - * - "element" - DOM Element or Node - * - "$node" or "$element" - jqLite-wrapped node or element - * - * - * Compiler related stuff: - * - * - "linkFn" - linking fn of a single directive - * - "nodeLinkFn" - function that aggregates all linking fns for a particular node - * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node - * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) - */ - - -var NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: '; - - -/** - * @ngdoc function - * @name ng.$compile - * @function - * - * @description - * Compiles a piece of HTML string or DOM into a template and produces a template function, which - * can then be used to link {@link ng.$rootScope.Scope scope} and the template together. - * - * The compilation is a process of walking the DOM tree and trying to match DOM elements to - * {@link ng.$compileProvider#directive directives}. For each match it - * executes corresponding template function and collects the - * instance functions into a single template function which is then returned. - * - * The template function can then be used once to produce the view or as it is the case with - * {@link ng.directive:ngRepeat repeater} many-times, in which - * case each call results in a view that is a DOM clone of the original template. - * - - - -
-
-
-
-
-
- - it('should auto compile', function() { - expect(element('div[compile]').text()).toBe('Hello Angular'); - input('html').enter('{{name}}!'); - expect(element('div[compile]').text()).toBe('Angular!'); - }); - -
- - * - * - * @param {string|DOMElement} element Element or HTML string to compile into a template function. - * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives. - * @param {number} maxPriority only apply directives lower then given priority (Only effects the - * root element(s), not their children) - * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template - * (a DOM element/tree) to a scope. Where: - * - * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. - * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the - * `template` and call the `cloneAttachFn` function allowing the caller to attach the - * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as:
`cloneAttachFn(clonedElement, scope)` where: - * - * * `clonedElement` - is a clone of the original `element` passed into the compiler. - * * `scope` - is the current scope with which the linking function is working with. - * - * Calling the linking function returns the element of the template. It is either the original element - * passed in, or the clone of the element if the `cloneAttachFn` is provided. - * - * After linking the view is not updated until after a call to $digest which typically is done by - * Angular automatically. - * - * If you need access to the bound view, there are two ways to do it: - * - * - If you are not asking the linking function to clone the template, create the DOM element(s) - * before you send them to the compiler and keep this reference around. - *
- *     var element = $compile('

{{total}}

')(scope); - *
- * - * - if on the other hand, you need the element to be cloned, the view reference from the original - * example would not point to the clone, but rather to the original template that was cloned. In - * this case, you can access the clone via the cloneAttachFn: - *
- *     var templateHTML = angular.element('

{{total}}

'), - * scope = ....; - * - * var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) { - * //attach the clone to DOM document at the right place - * }); - * - * //now we have reference to the cloned DOM via `clone` - *
- * - * - * For information on how the compiler works, see the - * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. - */ - - -/** - * @ngdoc service - * @name ng.$compileProvider - * @function - * - * @description - */ -$CompileProvider.$inject = ['$provide']; -function $CompileProvider($provide) { - var hasDirectives = {}, - Suffix = 'Directive', - COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/, - MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ', - urlSanitizationWhitelist = /^\s*(https?|ftp|mailto|file):/; - - - /** - * @ngdoc function - * @name ng.$compileProvider#directive - * @methodOf ng.$compileProvider - * @function - * - * @description - * Register a new directives with the compiler. - * - * @param {string} name Name of the directive in camel-case. (ie ngBind which will match as - * ng-bind). - * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more - * info. - * @returns {ng.$compileProvider} Self for chaining. - */ - this.directive = function registerDirective(name, directiveFactory) { - if (isString(name)) { - assertArg(directiveFactory, 'directive'); - if (!hasDirectives.hasOwnProperty(name)) { - hasDirectives[name] = []; - $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', - function($injector, $exceptionHandler) { - var directives = []; - forEach(hasDirectives[name], function(directiveFactory) { - try { - var directive = $injector.invoke(directiveFactory); - if (isFunction(directive)) { - directive = { compile: valueFn(directive) }; - } else if (!directive.compile && directive.link) { - directive.compile = valueFn(directive.link); - } - directive.priority = directive.priority || 0; - directive.name = directive.name || name; - directive.require = directive.require || (directive.controller && directive.name); - directive.restrict = directive.restrict || 'A'; - directives.push(directive); - } catch (e) { - $exceptionHandler(e); - } - }); - return directives; - }]); - } - hasDirectives[name].push(directiveFactory); - } else { - forEach(name, reverseParams(registerDirective)); - } - return this; - }; - - - /** - * @ngdoc function - * @name ng.$compileProvider#urlSanitizationWhitelist - * @methodOf ng.$compileProvider - * @function - * - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. - * - * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an - * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular - * expression. If a match is found the original url is written into the dom. Otherwise the - * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.urlSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - urlSanitizationWhitelist = regexp; - return this; - } - return urlSanitizationWhitelist; - }; - - - this.$get = [ - '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse', - '$controller', '$rootScope', '$document', - function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse, - $controller, $rootScope, $document) { - - var Attributes = function(element, attr) { - this.$$element = element; - this.$attr = attr || {}; - }; - - Attributes.prototype = { - $normalize: directiveNormalize, - - - /** - * Set a normalized attribute on the element in a way such that all directives - * can share the attribute. This function properly handles boolean attributes. - * @param {string} key Normalized key. (ie ngAttribute) - * @param {string|boolean} value The value to set. If `null` attribute will be deleted. - * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. - * Defaults to true. - * @param {string=} attrName Optional none normalized name. Defaults to key. - */ - $set: function(key, value, writeAttr, attrName) { - var booleanKey = getBooleanAttrName(this.$$element[0], key), - $$observers = this.$$observers, - normalizedVal; - - if (booleanKey) { - this.$$element.prop(key, value); - attrName = booleanKey; - } - - this[key] = value; - - // translate normalized key to actual key - if (attrName) { - this.$attr[key] = attrName; - } else { - attrName = this.$attr[key]; - if (!attrName) { - this.$attr[key] = attrName = snake_case(key, '-'); - } - } - - - // sanitize a[href] values - if (nodeName_(this.$$element[0]) === 'A' && key === 'href') { - urlSanitizationNode.setAttribute('href', value); - - // href property always returns normalized absolute url, so we can match against that - normalizedVal = urlSanitizationNode.href; - if (!normalizedVal.match(urlSanitizationWhitelist)) { - this[key] = value = 'unsafe:' + normalizedVal; - } - } - - - if (writeAttr !== false) { - if (value === null || value === undefined) { - this.$$element.removeAttr(attrName); - } else { - this.$$element.attr(attrName, value); - } - } - - // fire observers - $$observers && forEach($$observers[key], function(fn) { - try { - fn(value); - } catch (e) { - $exceptionHandler(e); - } - }); - }, - - - /** - * Observe an interpolated attribute. - * The observer will never be called, if given attribute is not interpolated. - * - * @param {string} key Normalized key. (ie ngAttribute) . - * @param {function(*)} fn Function that will be called whenever the attribute value changes. - * @returns {function(*)} the `fn` Function passed in. - */ - $observe: function(key, fn) { - var attrs = this, - $$observers = (attrs.$$observers || (attrs.$$observers = {})), - listeners = ($$observers[key] || ($$observers[key] = [])); - - listeners.push(fn); - $rootScope.$evalAsync(function() { - if (!listeners.$$inter) { - // no one registered attribute interpolation function, so lets call it manually - fn(attrs[key]); - } - }); - return fn; - } - }; - - var urlSanitizationNode = $document[0].createElement('a'), - startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') - ? identity - : function denormalizeTemplate(template) { - return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); - }; - - - return compile; - - //================================ - - function compile($compileNodes, transcludeFn, maxPriority) { - if (!($compileNodes instanceof jqLite)) { - // jquery always rewraps, whereas we need to preserve the original selector so that we can modify it. - $compileNodes = jqLite($compileNodes); - } - // We can not compile top level text elements since text nodes can be merged and we will - // not be able to attach scope data to them, so we will wrap them in - forEach($compileNodes, function(node, index){ - if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) { - $compileNodes[index] = jqLite(node).wrap('').parent()[0]; - } - }); - var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority); - return function publicLinkFn(scope, cloneConnectFn){ - assertArg(scope, 'scope'); - // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart - // and sometimes changes the structure of the DOM. - var $linkNode = cloneConnectFn - ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!! - : $compileNodes; - - // Attach scope only to non-text nodes. - for(var i = 0, ii = $linkNode.length; i - addDirective(directives, - directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority); - - // iterate over the attributes - for (var attr, name, nName, value, nAttrs = node.attributes, - j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { - attr = nAttrs[j]; - if (attr.specified) { - name = attr.name; - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - attrs[nName] = value = trim((msie && name == 'href') - ? decodeURIComponent(node.getAttribute(name, 2)) - : attr.value); - if (getBooleanAttrName(node, nName)) { - attrs[nName] = true; // presence means true - } - addAttrInterpolateDirective(node, directives, value, nName); - addDirective(directives, nName, 'A', maxPriority); - } - } - - // use class as directive - className = node.className; - if (isString(className) && className !== '') { - while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { - nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, 'C', maxPriority)) { - attrs[nName] = trim(match[3]); - } - className = className.substr(match.index + match[0].length); - } - } - break; - case 3: /* Text Node */ - addTextInterpolateDirective(directives, node.nodeValue); - break; - case 8: /* Comment */ - try { - match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, 'M', maxPriority)) { - attrs[nName] = trim(match[2]); - } - } - } catch (e) { - // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value. - // Just ignore it and continue. (Can't seem to reproduce in test case.) - } - break; - } - - directives.sort(byPriority); - return directives; - } - - - /** - * Once the directives have been collected, their compile functions are executed. This method - * is responsible for inlining directive templates as well as terminating the application - * of the directives if the terminal directive has been reached. - * - * @param {Array} directives Array of collected directives to execute their compile function. - * this needs to be pre-sorted by priority order. - * @param {Node} compileNode The raw DOM node to apply the compile functions to - * @param {Object} templateAttrs The shared attribute function - * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the - * scope argument is auto-generated to the new child of the transcluded parent scope. - * @param {JQLite} jqCollection If we are working on the root of the compile tree then this - * argument has the root jqLite array so that we can replace nodes on it. - * @returns linkFn - */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection) { - var terminalPriority = -Number.MAX_VALUE, - preLinkFns = [], - postLinkFns = [], - newScopeDirective = null, - newIsolateScopeDirective = null, - templateDirective = null, - $compileNode = templateAttrs.$$element = jqLite(compileNode), - directive, - directiveName, - $template, - transcludeDirective, - childTranscludeFn = transcludeFn, - controllerDirectives, - linkFn, - directiveValue; - - // executes all directives on the current element - for(var i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - $template = undefined; - - if (terminalPriority > directive.priority) { - break; // prevent further processing of directives - } - - if (directiveValue = directive.scope) { - assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode); - if (isObject(directiveValue)) { - safeAddClass($compileNode, 'ng-isolate-scope'); - newIsolateScopeDirective = directive; - } - safeAddClass($compileNode, 'ng-scope'); - newScopeDirective = newScopeDirective || directive; - } - - directiveName = directive.name; - - if (directiveValue = directive.controller) { - controllerDirectives = controllerDirectives || {}; - assertNoDuplicate("'" + directiveName + "' controller", - controllerDirectives[directiveName], directive, $compileNode); - controllerDirectives[directiveName] = directive; - } - - if (directiveValue = directive.transclude) { - assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode); - transcludeDirective = directive; - terminalPriority = directive.priority; - if (directiveValue == 'element') { - $template = jqLite(compileNode); - $compileNode = templateAttrs.$$element = - jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' ')); - compileNode = $compileNode[0]; - replaceWith(jqCollection, jqLite($template[0]), compileNode); - childTranscludeFn = compile($template, transcludeFn, terminalPriority); - } else { - $template = jqLite(JQLiteClone(compileNode)).contents(); - $compileNode.html(''); // clear contents - childTranscludeFn = compile($template, transcludeFn); - } - } - - if ((directiveValue = directive.template)) { - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - directiveValue = denormalizeTemplate(directiveValue); - - if (directive.replace) { - $template = jqLite('
' + - trim(directiveValue) + - '
').contents(); - compileNode = $template[0]; - - if ($template.length != 1 || compileNode.nodeType !== 1) { - throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue); - } - - replaceWith(jqCollection, $compileNode, compileNode); - - var newTemplateAttrs = {$attr: {}}; - - // combine directives from the original node and from the template: - // - take the array of directives for this element - // - split it into two parts, those that were already applied and those that weren't - // - collect directives from the template, add them to the second group and sort them - // - append the second group with new directives to the first group - directives = directives.concat( - collectDirectives( - compileNode, - directives.splice(i + 1, directives.length - (i + 1)), - newTemplateAttrs - ) - ); - mergeTemplateAttributes(templateAttrs, newTemplateAttrs); - - ii = directives.length; - } else { - $compileNode.html(directiveValue); - } - } - - if (directive.templateUrl) { - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), - nodeLinkFn, $compileNode, templateAttrs, jqCollection, directive.replace, - childTranscludeFn); - ii = directives.length; - } else if (directive.compile) { - try { - linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); - if (isFunction(linkFn)) { - addLinkFns(null, linkFn); - } else if (linkFn) { - addLinkFns(linkFn.pre, linkFn.post); - } - } catch (e) { - $exceptionHandler(e, startingTag($compileNode)); - } - } - - if (directive.terminal) { - nodeLinkFn.terminal = true; - terminalPriority = Math.max(terminalPriority, directive.priority); - } - - } - - nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope; - nodeLinkFn.transclude = transcludeDirective && childTranscludeFn; - - // might be normal or delayed nodeLinkFn depending on if templateUrl is present - return nodeLinkFn; - - //////////////////// - - function addLinkFns(pre, post) { - if (pre) { - pre.require = directive.require; - preLinkFns.push(pre); - } - if (post) { - post.require = directive.require; - postLinkFns.push(post); - } - } - - - function getControllers(require, $element) { - var value, retrievalMethod = 'data', optional = false; - if (isString(require)) { - while((value = require.charAt(0)) == '^' || value == '?') { - require = require.substr(1); - if (value == '^') { - retrievalMethod = 'inheritedData'; - } - optional = optional || value == '?'; - } - value = $element[retrievalMethod]('$' + require + 'Controller'); - if (!value && !optional) { - throw Error("No controller: " + require); - } - return value; - } else if (isArray(require)) { - value = []; - forEach(require, function(require) { - value.push(getControllers(require, $element)); - }); - } - return value; - } - - - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { - var attrs, $element, i, ii, linkFn, controller; - - if (compileNode === linkNode) { - attrs = templateAttrs; - } else { - attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr)); - } - $element = attrs.$$element; - - if (newIsolateScopeDirective) { - var LOCAL_REGEXP = /^\s*([@=&])\s*(\w*)\s*$/; - - var parentScope = scope.$parent || scope; - - forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) { - var match = definiton.match(LOCAL_REGEXP) || [], - attrName = match[2]|| scopeName, - mode = match[1], // @, =, or & - lastValue, - parentGet, parentSet; - - scope.$$isolateBindings[scopeName] = mode + attrName; - - switch (mode) { - - case '@': { - attrs.$observe(attrName, function(value) { - scope[scopeName] = value; - }); - attrs.$$observers[attrName].$$scope = parentScope; - break; - } - - case '=': { - parentGet = $parse(attrs[attrName]); - parentSet = parentGet.assign || function() { - // reset the change, or we will throw this exception on every $digest - lastValue = scope[scopeName] = parentGet(parentScope); - throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] + - ' (directive: ' + newIsolateScopeDirective.name + ')'); - }; - lastValue = scope[scopeName] = parentGet(parentScope); - scope.$watch(function parentValueWatch() { - var parentValue = parentGet(parentScope); - - if (parentValue !== scope[scopeName]) { - // we are out of sync and need to copy - if (parentValue !== lastValue) { - // parent changed and it has precedence - lastValue = scope[scopeName] = parentValue; - } else { - // if the parent can be assigned then do so - parentSet(parentScope, parentValue = lastValue = scope[scopeName]); - } - } - return parentValue; - }); - break; - } - - case '&': { - parentGet = $parse(attrs[attrName]); - scope[scopeName] = function(locals) { - return parentGet(parentScope, locals); - }; - break; - } - - default: { - throw Error('Invalid isolate scope definition for directive ' + - newIsolateScopeDirective.name + ': ' + definiton); - } - } - }); - } - - if (controllerDirectives) { - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: scope, - $element: $element, - $attrs: attrs, - $transclude: boundTranscludeFn - }; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - $element.data( - '$' + directive.name + 'Controller', - $controller(controller, locals)); - }); - } - - // PRELINKING - for(i = 0, ii = preLinkFns.length; i < ii; i++) { - try { - linkFn = preLinkFns[i]; - linkFn(scope, $element, attrs, - linkFn.require && getControllers(linkFn.require, $element)); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - - // RECURSION - childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn); - - // POSTLINKING - for(i = 0, ii = postLinkFns.length; i < ii; i++) { - try { - linkFn = postLinkFns[i]; - linkFn(scope, $element, attrs, - linkFn.require && getControllers(linkFn.require, $element)); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - } - } - - - /** - * looks up the directive and decorates it with exception handling and proper parameters. We - * call this the boundDirective. - * - * @param {string} name name of the directive to look up. - * @param {string} location The directive must be found in specific format. - * String containing any of theses characters: - * - * * `E`: element name - * * `A': attribute - * * `C`: class - * * `M`: comment - * @returns true if directive was added. - */ - function addDirective(tDirectives, name, location, maxPriority) { - var match = false; - if (hasDirectives.hasOwnProperty(name)) { - for(var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i directive.priority) && - directive.restrict.indexOf(location) != -1) { - tDirectives.push(directive); - match = true; - } - } catch(e) { $exceptionHandler(e); } - } - } - return match; - } - - - /** - * When the element is replaced with HTML template then the new attributes - * on the template need to be merged with the existing attributes in the DOM. - * The desired effect is to have both of the attributes present. - * - * @param {object} dst destination attributes (original DOM) - * @param {object} src source attributes (from the directive template) - */ - function mergeTemplateAttributes(dst, src) { - var srcAttr = src.$attr, - dstAttr = dst.$attr, - $element = dst.$$element; - - // reapply the old attributes to the new element - forEach(dst, function(value, key) { - if (key.charAt(0) != '$') { - if (src[key]) { - value += (key === 'style' ? ';' : ' ') + src[key]; - } - dst.$set(key, value, true, srcAttr[key]); - } - }); - - // copy the new attributes on the old attrs object - forEach(src, function(value, key) { - if (key == 'class') { - safeAddClass($element, value); - dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; - } else if (key == 'style') { - $element.attr('style', $element.attr('style') + ';' + value); - } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { - dst[key] = value; - dstAttr[key] = srcAttr[key]; - } - }); - } - - - function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs, - $rootElement, replace, childTranscludeFn) { - var linkQueue = [], - afterTemplateNodeLinkFn, - afterTemplateChildLinkFn, - beforeTemplateCompileNode = $compileNode[0], - origAsyncDirective = directives.shift(), - // The fact that we have to copy and patch the directive seems wrong! - derivedSyncDirective = extend({}, origAsyncDirective, { - controller: null, templateUrl: null, transclude: null, scope: null - }); - - $compileNode.html(''); - - $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}). - success(function(content) { - var compileNode, tempTemplateAttrs, $template; - - content = denormalizeTemplate(content); - - if (replace) { - $template = jqLite('
' + trim(content) + '
').contents(); - compileNode = $template[0]; - - if ($template.length != 1 || compileNode.nodeType !== 1) { - throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content); - } - - tempTemplateAttrs = {$attr: {}}; - replaceWith($rootElement, $compileNode, compileNode); - collectDirectives(compileNode, directives, tempTemplateAttrs); - mergeTemplateAttributes(tAttrs, tempTemplateAttrs); - } else { - compileNode = beforeTemplateCompileNode; - $compileNode.html(content); - } - - directives.unshift(derivedSyncDirective); - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn); - afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); - - - while(linkQueue.length) { - var controller = linkQueue.pop(), - linkRootElement = linkQueue.pop(), - beforeTemplateLinkNode = linkQueue.pop(), - scope = linkQueue.pop(), - linkNode = compileNode; - - if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - // it was cloned therefore we have to clone as well. - linkNode = JQLiteClone(compileNode); - replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); - } - - afterTemplateNodeLinkFn(function() { - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller); - }, scope, linkNode, $rootElement, controller); - } - linkQueue = null; - }). - error(function(response, code, headers, config) { - throw Error('Failed to load template: ' + config.url); - }); - - return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) { - if (linkQueue) { - linkQueue.push(scope); - linkQueue.push(node); - linkQueue.push(rootElement); - linkQueue.push(controller); - } else { - afterTemplateNodeLinkFn(function() { - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller); - }, scope, node, rootElement, controller); - } - }; - } - - - /** - * Sorting function for bound directives. - */ - function byPriority(a, b) { - return b.priority - a.priority; - } - - - function assertNoDuplicate(what, previousDirective, directive, element) { - if (previousDirective) { - throw Error('Multiple directives [' + previousDirective.name + ', ' + - directive.name + '] asking for ' + what + ' on: ' + startingTag(element)); - } - } - - - function addTextInterpolateDirective(directives, text) { - var interpolateFn = $interpolate(text, true); - if (interpolateFn) { - directives.push({ - priority: 0, - compile: valueFn(function textInterpolateLinkFn(scope, node) { - var parent = node.parent(), - bindings = parent.data('$binding') || []; - bindings.push(interpolateFn); - safeAddClass(parent.data('$binding', bindings), 'ng-binding'); - scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { - node[0].nodeValue = value; - }); - }) - }); - } - } - - - function addAttrInterpolateDirective(node, directives, value, name) { - var interpolateFn = $interpolate(value, true); - - // no interpolation found -> ignore - if (!interpolateFn) return; - - - directives.push({ - priority: 100, - compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = {})); - - if (name === 'class') { - // we need to interpolate classes again, in the case the element was replaced - // and therefore the two class attrs got merged - we want to interpolate the result - interpolateFn = $interpolate(attr[name], true); - } - - attr[name] = undefined; - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope). - $watch(interpolateFn, function interpolateFnWatchAction(value) { - attr.$set(name, value); - }); - }) - }); - } - - - /** - * This is a special jqLite.replaceWith, which can replace items which - * have no parents, provided that the containing jqLite collection is provided. - * - * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes - * in the root of the tree. - * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell, - * but replace its DOM node reference. - * @param {Node} newNode The new DOM node. - */ - function replaceWith($rootElement, $element, newNode) { - var oldNode = $element[0], - parent = oldNode.parentNode, - i, ii; - - if ($rootElement) { - for(i = 0, ii = $rootElement.length; i < ii; i++) { - if ($rootElement[i] == oldNode) { - $rootElement[i] = newNode; - break; - } - } - } - - if (parent) { - parent.replaceChild(newNode, oldNode); - } - - newNode[jqLite.expando] = oldNode[jqLite.expando]; - $element[0] = newNode; - } - }]; -} - -var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i; -/** - * Converts all accepted directives format into proper directive name. - * All of these will become 'myDirective': - * my:DiRective - * my-directive - * x-my-directive - * data-my:directive - * - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize - */ -function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, '')); -} - -/** - * @ngdoc object - * @name ng.$compile.directive.Attributes - * @description - * - * A shared object between directive compile / linking functions which contains normalized DOM element - * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed - * since all of these are treated as equivalent in Angular: - * - * - */ - -/** - * @ngdoc property - * @name ng.$compile.directive.Attributes#$attr - * @propertyOf ng.$compile.directive.Attributes - * @returns {object} A map of DOM element attribute names to the normalized name. This is - * needed to do reverse lookup from normalized name back to actual name. - */ - - -/** - * @ngdoc function - * @name ng.$compile.directive.Attributes#$set - * @methodOf ng.$compile.directive.Attributes - * @function - * - * @description - * Set DOM element attribute value. - * - * - * @param {string} name Normalized element attribute name of the property to modify. The name is - * revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr} - * property to the original name. - * @param {string} value Value to set the attribute to. - */ - - - -/** - * Closure compiler type information - */ - -function nodesetLinkingFn( - /* angular.Scope */ scope, - /* NodeList */ nodeList, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -){} - -function directiveLinkingFn( - /* nodesetLinkingFn */ nodesetLinkingFn, - /* angular.Scope */ scope, - /* Node */ node, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -){} - -/** - * @ngdoc object - * @name ng.$controllerProvider - * @description - * The {@link ng.$controller $controller service} is used by Angular to create new - * controllers. - * - * This provider allows controller registration via the - * {@link ng.$controllerProvider#register register} method. - */ -function $ControllerProvider() { - var controllers = {}; - - - /** - * @ngdoc function - * @name ng.$controllerProvider#register - * @methodOf ng.$controllerProvider - * @param {string} name Controller name - * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI - * annotations in the array notation). - */ - this.register = function(name, constructor) { - if (isObject(name)) { - extend(controllers, name) - } else { - controllers[name] = constructor; - } - }; - - - this.$get = ['$injector', '$window', function($injector, $window) { - - /** - * @ngdoc function - * @name ng.$controller - * @requires $injector - * - * @param {Function|string} constructor If called with a function then it's considered to be the - * controller constructor function. Otherwise it's considered to be a string which is used - * to retrieve the controller constructor using the following steps: - * - * * check if a controller with given name is registered via `$controllerProvider` - * * check if evaluating the string on the current scope returns a constructor - * * check `window[constructor]` on the global `window` object - * - * @param {Object} locals Injection locals for Controller. - * @return {Object} Instance of given controller. - * - * @description - * `$controller` service is responsible for instantiating controllers. - * - * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into - * a service, so that one can override this service with {@link https://gist.github.com/1649788 - * BC version}. - */ - return function(constructor, locals) { - if(isString(constructor)) { - var name = constructor; - constructor = controllers.hasOwnProperty(name) - ? controllers[name] - : getter(locals.$scope, name, true) || getter($window, name, true); - - assertArgFn(constructor, name, true); - } - - return $injector.instantiate(constructor, locals); - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$document - * @requires $window - * - * @description - * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document` - * element. - */ -function $DocumentProvider(){ - this.$get = ['$window', function(window){ - return jqLite(window.document); - }]; -} - -/** - * @ngdoc function - * @name ng.$exceptionHandler - * @requires $log - * - * @description - * Any uncaught exception in angular expressions is delegated to this service. - * The default implementation simply delegates to `$log.error` which logs it into - * the browser console. - * - * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by - * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. - * - * @param {Error} exception Exception associated with the error. - * @param {string=} cause optional information about the context in which - * the error was thrown. - * - */ -function $ExceptionHandlerProvider() { - this.$get = ['$log', function($log) { - return function(exception, cause) { - $log.error.apply($log, arguments); - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$interpolateProvider - * @function - * - * @description - * - * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. - */ -function $InterpolateProvider() { - var startSymbol = '{{'; - var endSymbol = '}}'; - - /** - * @ngdoc method - * @name ng.$interpolateProvider#startSymbol - * @methodOf ng.$interpolateProvider - * @description - * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. - * - * @param {string=} value new value to set the starting symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.startSymbol = function(value){ - if (value) { - startSymbol = value; - return this; - } else { - return startSymbol; - } - }; - - /** - * @ngdoc method - * @name ng.$interpolateProvider#endSymbol - * @methodOf ng.$interpolateProvider - * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. - * - * @param {string=} value new value to set the ending symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.endSymbol = function(value){ - if (value) { - endSymbol = value; - return this; - } else { - return endSymbol; - } - }; - - - this.$get = ['$parse', function($parse) { - var startSymbolLength = startSymbol.length, - endSymbolLength = endSymbol.length; - - /** - * @ngdoc function - * @name ng.$interpolate - * @function - * - * @requires $parse - * - * @description - * - * Compiles a string with markup into an interpolation function. This service is used by the - * HTML {@link ng.$compile $compile} service for data binding. See - * {@link ng.$interpolateProvider $interpolateProvider} for configuring the - * interpolation markup. - * - * -
-         var $interpolate = ...; // injected
-         var exp = $interpolate('Hello {{name}}!');
-         expect(exp({name:'Angular'}).toEqual('Hello Angular!');
-       
- * - * - * @param {string} text The text with markup to interpolate. - * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have - * embedded expression in order to return an interpolation function. Strings with no - * embedded expression will return null for the interpolation function. - * @returns {function(context)} an interpolation function which is used to compute the interpolated - * string. The function has these parameters: - * - * * `context`: an object against which any expressions embedded in the strings are evaluated - * against. - * - */ - function $interpolate(text, mustHaveExpression) { - var startIndex, - endIndex, - index = 0, - parts = [], - length = text.length, - hasInterpolation = false, - fn, - exp, - concat = []; - - while(index < length) { - if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) && - ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) { - (index != startIndex) && parts.push(text.substring(index, startIndex)); - parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex))); - fn.exp = exp; - index = endIndex + endSymbolLength; - hasInterpolation = true; - } else { - // we did not find anything, so we have to add the remainder to the parts array - (index != length) && parts.push(text.substring(index)); - index = length; - } - } - - if (!(length = parts.length)) { - // we added, nothing, must have been an empty string. - parts.push(''); - length = 1; - } - - if (!mustHaveExpression || hasInterpolation) { - concat.length = length; - fn = function(context) { - for(var i = 0, ii = length, part; i html5 url - } else { - return composeProtocolHostPort(match.protocol, match.host, match.port) + - pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length); - } -} - - -function convertToHashbangUrl(url, basePath, hashPrefix) { - var match = matchUrl(url); - - // already hashbang url - if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) && - match.hash.indexOf(hashPrefix) === 0) { - return url; - // convert html5 url -> hashbang url - } else { - var search = match.search && '?' + match.search || '', - hash = match.hash && '#' + match.hash || '', - pathPrefix = pathPrefixFromBase(basePath), - path = match.path.substr(pathPrefix.length); - - if (match.path.indexOf(pathPrefix) !== 0) { - throw Error('Invalid url "' + url + '", missing path prefix "' + pathPrefix + '" !'); - } - - return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath + - '#' + hashPrefix + path + search + hash; - } -} - - -/** - * LocationUrl represents an url - * This object is exposed as $location service when HTML5 mode is enabled and supported - * - * @constructor - * @param {string} url HTML5 url - * @param {string} pathPrefix - */ -function LocationUrl(url, pathPrefix, appBaseUrl) { - pathPrefix = pathPrefix || ''; - - /** - * Parse given html5 (regular) url string into properties - * @param {string} newAbsoluteUrl HTML5 url - * @private - */ - this.$$parse = function(newAbsoluteUrl) { - var match = matchUrl(newAbsoluteUrl, this); - - if (match.path.indexOf(pathPrefix) !== 0) { - throw Error('Invalid url "' + newAbsoluteUrl + '", missing path prefix "' + pathPrefix + '" !'); - } - - this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length)); - this.$$search = parseKeyValue(match.search); - this.$$hash = match.hash && decodeURIComponent(match.hash) || ''; - - this.$$compose(); - }; - - /** - * Compose url and update `absUrl` property - * @private - */ - this.$$compose = function() { - var search = toKeyValue(this.$$search), - hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; - - this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) + - pathPrefix + this.$$url; - }; - - - this.$$rewriteAppUrl = function(absoluteLinkUrl) { - if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) { - return absoluteLinkUrl; - } - } - - - this.$$parse(url); -} - - -/** - * LocationHashbangUrl represents url - * This object is exposed as $location service when html5 history api is disabled or not supported - * - * @constructor - * @param {string} url Legacy url - * @param {string} hashPrefix Prefix for hash part (containing path and search) - */ -function LocationHashbangUrl(url, hashPrefix, appBaseUrl) { - var basePath; - - /** - * Parse given hashbang url into properties - * @param {string} url Hashbang url - * @private - */ - this.$$parse = function(url) { - var match = matchUrl(url, this); - - - if (match.hash && match.hash.indexOf(hashPrefix) !== 0) { - throw Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '" !'); - } - - basePath = match.path + (match.search ? '?' + match.search : ''); - match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length)); - if (match[1]) { - this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]); - } else { - this.$$path = ''; - } - - this.$$search = parseKeyValue(match[3]); - this.$$hash = match[5] && decodeURIComponent(match[5]) || ''; - - this.$$compose(); - }; - - /** - * Compose hashbang url and update `absUrl` property - * @private - */ - this.$$compose = function() { - var search = toKeyValue(this.$$search), - hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; - - this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) + - basePath + (this.$$url ? '#' + hashPrefix + this.$$url : ''); - }; - - this.$$rewriteAppUrl = function(absoluteLinkUrl) { - if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) { - return absoluteLinkUrl; - } - } - - - this.$$parse(url); -} - - -LocationUrl.prototype = { - - /** - * Has any change been replacing ? - * @private - */ - $$replace: false, - - /** - * @ngdoc method - * @name ng.$location#absUrl - * @methodOf ng.$location - * - * @description - * This method is getter only. - * - * Return full url representation with all segments encoded according to rules specified in - * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}. - * - * @return {string} full url - */ - absUrl: locationGetter('$$absUrl'), - - /** - * @ngdoc method - * @name ng.$location#url - * @methodOf ng.$location - * - * @description - * This method is getter / setter. - * - * Return url (e.g. `/path?a=b#hash`) when called without any parameter. - * - * Change path, search and hash, when called with parameter and return `$location`. - * - * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) - * @return {string} url - */ - url: function(url, replace) { - if (isUndefined(url)) - return this.$$url; - - var match = PATH_MATCH.exec(url); - if (match[1]) this.path(decodeURIComponent(match[1])); - if (match[2] || match[1]) this.search(match[3] || ''); - this.hash(match[5] || '', replace); - - return this; - }, - - /** - * @ngdoc method - * @name ng.$location#protocol - * @methodOf ng.$location - * - * @description - * This method is getter only. - * - * Return protocol of current url. - * - * @return {string} protocol of current url - */ - protocol: locationGetter('$$protocol'), - - /** - * @ngdoc method - * @name ng.$location#host - * @methodOf ng.$location - * - * @description - * This method is getter only. - * - * Return host of current url. - * - * @return {string} host of current url. - */ - host: locationGetter('$$host'), - - /** - * @ngdoc method - * @name ng.$location#port - * @methodOf ng.$location - * - * @description - * This method is getter only. - * - * Return port of current url. - * - * @return {Number} port - */ - port: locationGetter('$$port'), - - /** - * @ngdoc method - * @name ng.$location#path - * @methodOf ng.$location - * - * @description - * This method is getter / setter. - * - * Return path of current url when called without any parameter. - * - * Change path when called with parameter and return `$location`. - * - * Note: Path should always begin with forward slash (/), this method will add the forward slash - * if it is missing. - * - * @param {string=} path New path - * @return {string} path - */ - path: locationGetterSetter('$$path', function(path) { - return path.charAt(0) == '/' ? path : '/' + path; - }), - - /** - * @ngdoc method - * @name ng.$location#search - * @methodOf ng.$location - * - * @description - * This method is getter / setter. - * - * Return search part (as object) of current url when called without any parameter. - * - * Change search part when called with parameter and return `$location`. - * - * @param {string|object=} search New search params - string or hash object - * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a - * single search parameter. If the value is `null`, the parameter will be deleted. - * - * @return {string} search - */ - search: function(search, paramValue) { - if (isUndefined(search)) - return this.$$search; - - if (isDefined(paramValue)) { - if (paramValue === null) { - delete this.$$search[search]; - } else { - this.$$search[search] = paramValue; - } - } else { - this.$$search = isString(search) ? parseKeyValue(search) : search; - } - - this.$$compose(); - return this; - }, - - /** - * @ngdoc method - * @name ng.$location#hash - * @methodOf ng.$location - * - * @description - * This method is getter / setter. - * - * Return hash fragment when called without any parameter. - * - * Change hash fragment when called with parameter and return `$location`. - * - * @param {string=} hash New hash fragment - * @return {string} hash - */ - hash: locationGetterSetter('$$hash', identity), - - /** - * @ngdoc method - * @name ng.$location#replace - * @methodOf ng.$location - * - * @description - * If called, all changes to $location during current `$digest` will be replacing current history - * record, instead of adding new one. - */ - replace: function() { - this.$$replace = true; - return this; - } -}; - -LocationHashbangUrl.prototype = inherit(LocationUrl.prototype); - -function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) { - LocationHashbangUrl.apply(this, arguments); - - - this.$$rewriteAppUrl = function(absoluteLinkUrl) { - if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) { - return appBaseUrl + baseExtra + '#' + hashPrefix + absoluteLinkUrl.substr(appBaseUrl.length); - } - } -} - -LocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype); - -function locationGetter(property) { - return function() { - return this[property]; - }; -} - - -function locationGetterSetter(property, preprocess) { - return function(value) { - if (isUndefined(value)) - return this[property]; - - this[property] = preprocess(value); - this.$$compose(); - - return this; - }; -} - - -/** - * @ngdoc object - * @name ng.$location - * - * @requires $browser - * @requires $sniffer - * @requires $rootElement - * - * @description - * The $location service parses the URL in the browser address bar (based on the - * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL - * available to your application. Changes to the URL in the address bar are reflected into - * $location service and changes to $location are reflected into the browser address bar. - * - * **The $location service:** - * - * - Exposes the current URL in the browser address bar, so you can - * - Watch and observe the URL. - * - Change the URL. - * - Synchronizes the URL with the browser when the user - * - Changes the address bar. - * - Clicks the back or forward button (or clicks a History link). - * - Clicks on a link. - * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). - * - * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular - * Services: Using $location} - */ - -/** - * @ngdoc object - * @name ng.$locationProvider - * @description - * Use the `$locationProvider` to configure how the application deep linking paths are stored. - */ -function $LocationProvider(){ - var hashPrefix = '', - html5Mode = false; - - /** - * @ngdoc property - * @name ng.$locationProvider#hashPrefix - * @methodOf ng.$locationProvider - * @description - * @param {string=} prefix Prefix for hash part (containing path and search) - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.hashPrefix = function(prefix) { - if (isDefined(prefix)) { - hashPrefix = prefix; - return this; - } else { - return hashPrefix; - } - }; - - /** - * @ngdoc property - * @name ng.$locationProvider#html5Mode - * @methodOf ng.$locationProvider - * @description - * @param {string=} mode Use HTML5 strategy if available. - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.html5Mode = function(mode) { - if (isDefined(mode)) { - html5Mode = mode; - return this; - } else { - return html5Mode; - } - }; - - this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', - function( $rootScope, $browser, $sniffer, $rootElement) { - var $location, - basePath, - pathPrefix, - initUrl = $browser.url(), - initUrlParts = matchUrl(initUrl), - appBaseUrl; - - if (html5Mode) { - basePath = $browser.baseHref() || '/'; - pathPrefix = pathPrefixFromBase(basePath); - appBaseUrl = - composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) + - pathPrefix + '/'; - - if ($sniffer.history) { - $location = new LocationUrl( - convertToHtml5Url(initUrl, basePath, hashPrefix), - pathPrefix, appBaseUrl); - } else { - $location = new LocationHashbangInHtml5Url( - convertToHashbangUrl(initUrl, basePath, hashPrefix), - hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1)); - } - } else { - appBaseUrl = - composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) + - (initUrlParts.path || '') + - (initUrlParts.search ? ('?' + initUrlParts.search) : '') + - '#' + hashPrefix + '/'; - - $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl); - } - - $rootElement.bind('click', function(event) { - // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) - // currently we open nice url link and redirect then - - if (event.ctrlKey || event.metaKey || event.which == 2) return; - - var elm = jqLite(event.target); - - // traverse the DOM up to find first A tag - while (lowercase(elm[0].nodeName) !== 'a') { - // ignore rewriting if no A tag (reached root element, or no parent - removed from document) - if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; - } - - var absHref = elm.prop('href'), - rewrittenUrl = $location.$$rewriteAppUrl(absHref); - - if (absHref && !elm.attr('target') && rewrittenUrl) { - // update location manually - $location.$$parse(rewrittenUrl); - $rootScope.$apply(); - event.preventDefault(); - // hack to work around FF6 bug 684208 when scenario runner clicks on links - window.angular['ff-684208-preventDefault'] = true; - } - }); - - - // rewrite hashbang url <> html5 url - if ($location.absUrl() != initUrl) { - $browser.url($location.absUrl(), true); - } - - // update $location when $browser url changes - $browser.onUrlChange(function(newUrl) { - if ($location.absUrl() != newUrl) { - if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) { - $browser.url($location.absUrl()); - return; - } - $rootScope.$evalAsync(function() { - var oldUrl = $location.absUrl(); - - $location.$$parse(newUrl); - afterLocationChange(oldUrl); - }); - if (!$rootScope.$$phase) $rootScope.$digest(); - } - }); - - // update browser - var changeCounter = 0; - $rootScope.$watch(function $locationWatch() { - var oldUrl = $browser.url(); - var currentReplace = $location.$$replace; - - if (!changeCounter || oldUrl != $location.absUrl()) { - changeCounter++; - $rootScope.$evalAsync(function() { - if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl). - defaultPrevented) { - $location.$$parse(oldUrl); - } else { - $browser.url($location.absUrl(), currentReplace); - afterLocationChange(oldUrl); - } - }); - } - $location.$$replace = false; - - return changeCounter; - }); - - return $location; - - function afterLocationChange(oldUrl) { - $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl); - } -}]; -} - -/** - * @ngdoc object - * @name ng.$log - * @requires $window - * - * @description - * Simple service for logging. Default implementation writes the message - * into the browser's console (if present). - * - * The main purpose of this service is to simplify debugging and troubleshooting. - * - * @example - - - function LogCtrl($scope, $log) { - $scope.$log = $log; - $scope.message = 'Hello World!'; - } - - -
-

Reload this page with open console, enter text and hit the log button...

- Message: - - - - - -
-
-
- */ - -function $LogProvider(){ - this.$get = ['$window', function($window){ - return { - /** - * @ngdoc method - * @name ng.$log#log - * @methodOf ng.$log - * - * @description - * Write a log message - */ - log: consoleLog('log'), - - /** - * @ngdoc method - * @name ng.$log#warn - * @methodOf ng.$log - * - * @description - * Write a warning message - */ - warn: consoleLog('warn'), - - /** - * @ngdoc method - * @name ng.$log#info - * @methodOf ng.$log - * - * @description - * Write an information message - */ - info: consoleLog('info'), - - /** - * @ngdoc method - * @name ng.$log#error - * @methodOf ng.$log - * - * @description - * Write an error message - */ - error: consoleLog('error') - }; - - function formatError(arg) { - if (arg instanceof Error) { - if (arg.stack) { - arg = (arg.message && arg.stack.indexOf(arg.message) === -1) - ? 'Error: ' + arg.message + '\n' + arg.stack - : arg.stack; - } else if (arg.sourceURL) { - arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; - } - } - return arg; - } - - function consoleLog(type) { - var console = $window.console || {}, - logFn = console[type] || console.log || noop; - - if (logFn.apply) { - return function() { - var args = []; - forEach(arguments, function(arg) { - args.push(formatError(arg)); - }); - return logFn.apply(console, args); - }; - } - - // we are IE which either doesn't have window.console => this is noop and we do nothing, - // or we are IE where console.log doesn't have apply so we log at least first 2 args - return function(arg1, arg2) { - logFn(arg1, arg2); - } - } - }]; -} - -var OPERATORS = { - 'null':function(){return null;}, - 'true':function(){return true;}, - 'false':function(){return false;}, - undefined:noop, - '+':function(self, locals, a,b){ - a=a(self, locals); b=b(self, locals); - if (isDefined(a)) { - if (isDefined(b)) { - return a + b; - } - return a; - } - return isDefined(b)?b:undefined;}, - '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, - '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);}, - '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);}, - '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);}, - '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);}, - '=':noop, - '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);}, - '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);}, - '<':function(self, locals, a,b){return a(self, locals)':function(self, locals, a,b){return a(self, locals)>b(self, locals);}, - '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);}, - '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);}, - '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);}, - '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);}, - '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);}, -// '|':function(self, locals, a,b){return a|b;}, - '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));}, - '!':function(self, locals, a){return !a(self, locals);} -}; -var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; - -function lex(text, csp){ - var tokens = [], - token, - index = 0, - json = [], - ch, - lastCh = ':'; // can start regexp - - while (index < text.length) { - ch = text.charAt(index); - if (is('"\'')) { - readString(ch); - } else if (isNumber(ch) || is('.') && isNumber(peek())) { - readNumber(); - } else if (isIdent(ch)) { - readIdent(); - // identifiers can only be if the preceding char was a { or , - if (was('{,') && json[0]=='{' && - (token=tokens[tokens.length-1])) { - token.json = token.text.indexOf('.') == -1; - } - } else if (is('(){}[].,;:')) { - tokens.push({ - index:index, - text:ch, - json:(was(':[,') && is('{[')) || is('}]:,') - }); - if (is('{[')) json.unshift(ch); - if (is('}]')) json.shift(); - index++; - } else if (isWhitespace(ch)) { - index++; - continue; - } else { - var ch2 = ch + peek(), - fn = OPERATORS[ch], - fn2 = OPERATORS[ch2]; - if (fn2) { - tokens.push({index:index, text:ch2, fn:fn2}); - index += 2; - } else if (fn) { - tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')}); - index += 1; - } else { - throwError("Unexpected next character ", index, index+1); - } - } - lastCh = ch; - } - return tokens; - - function is(chars) { - return chars.indexOf(ch) != -1; - } - - function was(chars) { - return chars.indexOf(lastCh) != -1; - } - - function peek() { - return index + 1 < text.length ? text.charAt(index + 1) : false; - } - function isNumber(ch) { - return '0' <= ch && ch <= '9'; - } - function isWhitespace(ch) { - return ch == ' ' || ch == '\r' || ch == '\t' || - ch == '\n' || ch == '\v' || ch == '\u00A0'; // IE treats non-breaking space as \u00A0 - } - function isIdent(ch) { - return 'a' <= ch && ch <= 'z' || - 'A' <= ch && ch <= 'Z' || - '_' == ch || ch == '$'; - } - function isExpOperator(ch) { - return ch == '-' || ch == '+' || isNumber(ch); - } - - function throwError(error, start, end) { - end = end || index; - throw Error("Lexer Error: " + error + " at column" + - (isDefined(start) - ? "s " + start + "-" + index + " [" + text.substring(start, end) + "]" - : " " + end) + - " in expression [" + text + "]."); - } - - function readNumber() { - var number = ""; - var start = index; - while (index < text.length) { - var ch = lowercase(text.charAt(index)); - if (ch == '.' || isNumber(ch)) { - number += ch; - } else { - var peekCh = peek(); - if (ch == 'e' && isExpOperator(peekCh)) { - number += ch; - } else if (isExpOperator(ch) && - peekCh && isNumber(peekCh) && - number.charAt(number.length - 1) == 'e') { - number += ch; - } else if (isExpOperator(ch) && - (!peekCh || !isNumber(peekCh)) && - number.charAt(number.length - 1) == 'e') { - throwError('Invalid exponent'); - } else { - break; - } - } - index++; - } - number = 1 * number; - tokens.push({index:start, text:number, json:true, - fn:function() {return number;}}); - } - function readIdent() { - var ident = "", - start = index, - lastDot, peekIndex, methodName, ch; - - while (index < text.length) { - ch = text.charAt(index); - if (ch == '.' || isIdent(ch) || isNumber(ch)) { - if (ch == '.') lastDot = index; - ident += ch; - } else { - break; - } - index++; - } - - //check if this is not a method invocation and if it is back out to last dot - if (lastDot) { - peekIndex = index; - while(peekIndex < text.length) { - ch = text.charAt(peekIndex); - if (ch == '(') { - methodName = ident.substr(lastDot - start + 1); - ident = ident.substr(0, lastDot - start); - index = peekIndex; - break; - } - if(isWhitespace(ch)) { - peekIndex++; - } else { - break; - } - } - } - - - var token = { - index:start, - text:ident - }; - - if (OPERATORS.hasOwnProperty(ident)) { - token.fn = token.json = OPERATORS[ident]; - } else { - var getter = getterFn(ident, csp); - token.fn = extend(function(self, locals) { - return (getter(self, locals)); - }, { - assign: function(self, value) { - return setter(self, ident, value); - } - }); - } - - tokens.push(token); - - if (methodName) { - tokens.push({ - index:lastDot, - text: '.', - json: false - }); - tokens.push({ - index: lastDot + 1, - text: methodName, - json: false - }); - } - } - - function readString(quote) { - var start = index; - index++; - var string = ""; - var rawString = quote; - var escape = false; - while (index < text.length) { - var ch = text.charAt(index); - rawString += ch; - if (escape) { - if (ch == 'u') { - var hex = text.substring(index + 1, index + 5); - if (!hex.match(/[\da-f]{4}/i)) - throwError( "Invalid unicode escape [\\u" + hex + "]"); - index += 4; - string += String.fromCharCode(parseInt(hex, 16)); - } else { - var rep = ESCAPE[ch]; - if (rep) { - string += rep; - } else { - string += ch; - } - } - escape = false; - } else if (ch == '\\') { - escape = true; - } else if (ch == quote) { - index++; - tokens.push({ - index:start, - text:rawString, - string:string, - json:true, - fn:function() { return string; } - }); - return; - } else { - string += ch; - } - index++; - } - throwError("Unterminated quote", start); - } -} - -///////////////////////////////////////// - -function parser(text, json, $filter, csp){ - var ZERO = valueFn(0), - value, - tokens = lex(text, csp), - assignment = _assignment, - functionCall = _functionCall, - fieldAccess = _fieldAccess, - objectIndex = _objectIndex, - filterChain = _filterChain; - - if(json){ - // The extra level of aliasing is here, just in case the lexer misses something, so that - // we prevent any accidental execution in JSON. - assignment = logicalOR; - functionCall = - fieldAccess = - objectIndex = - filterChain = - function() { throwError("is not valid json", {text:text, index:0}); }; - value = primary(); - } else { - value = statements(); - } - if (tokens.length !== 0) { - throwError("is an unexpected token", tokens[0]); - } - return value; - - /////////////////////////////////// - function throwError(msg, token) { - throw Error("Syntax Error: Token '" + token.text + - "' " + msg + " at column " + - (token.index + 1) + " of the expression [" + - text + "] starting at [" + text.substring(token.index) + "]."); - } - - function peekToken() { - if (tokens.length === 0) - throw Error("Unexpected end of expression: " + text); - return tokens[0]; - } - - function peek(e1, e2, e3, e4) { - if (tokens.length > 0) { - var token = tokens[0]; - var t = token.text; - if (t==e1 || t==e2 || t==e3 || t==e4 || - (!e1 && !e2 && !e3 && !e4)) { - return token; - } - } - return false; - } - - function expect(e1, e2, e3, e4){ - var token = peek(e1, e2, e3, e4); - if (token) { - if (json && !token.json) { - throwError("is not valid json", token); - } - tokens.shift(); - return token; - } - return false; - } - - function consume(e1){ - if (!expect(e1)) { - throwError("is unexpected, expecting [" + e1 + "]", peek()); - } - } - - function unaryFn(fn, right) { - return function(self, locals) { - return fn(self, locals, right); - }; - } - - function binaryFn(left, fn, right) { - return function(self, locals) { - return fn(self, locals, left, right); - }; - } - - function statements() { - var statements = []; - while(true) { - if (tokens.length > 0 && !peek('}', ')', ';', ']')) - statements.push(filterChain()); - if (!expect(';')) { - // optimize for the common case where there is only one statement. - // TODO(size): maybe we should not support multiple statements? - return statements.length == 1 - ? statements[0] - : function(self, locals){ - var value; - for ( var i = 0; i < statements.length; i++) { - var statement = statements[i]; - if (statement) - value = statement(self, locals); - } - return value; - }; - } - } - } - - function _filterChain() { - var left = expression(); - var token; - while(true) { - if ((token = expect('|'))) { - left = binaryFn(left, token.fn, filter()); - } else { - return left; - } - } - } - - function filter() { - var token = expect(); - var fn = $filter(token.text); - var argsFn = []; - while(true) { - if ((token = expect(':'))) { - argsFn.push(expression()); - } else { - var fnInvoke = function(self, locals, input){ - var args = [input]; - for ( var i = 0; i < argsFn.length; i++) { - args.push(argsFn[i](self, locals)); - } - return fn.apply(self, args); - }; - return function() { - return fnInvoke; - }; - } - } - } - - function expression() { - return assignment(); - } - - function _assignment() { - var left = logicalOR(); - var right; - var token; - if ((token = expect('='))) { - if (!left.assign) { - throwError("implies assignment but [" + - text.substring(0, token.index) + "] can not be assigned to", token); - } - right = logicalOR(); - return function(scope, locals){ - return left.assign(scope, right(scope, locals), locals); - }; - } else { - return left; - } - } - - function logicalOR() { - var left = logicalAND(); - var token; - while(true) { - if ((token = expect('||'))) { - left = binaryFn(left, token.fn, logicalAND()); - } else { - return left; - } - } - } - - function logicalAND() { - var left = equality(); - var token; - if ((token = expect('&&'))) { - left = binaryFn(left, token.fn, logicalAND()); - } - return left; - } - - function equality() { - var left = relational(); - var token; - if ((token = expect('==','!='))) { - left = binaryFn(left, token.fn, equality()); - } - return left; - } - - function relational() { - var left = additive(); - var token; - if ((token = expect('<', '>', '<=', '>='))) { - left = binaryFn(left, token.fn, relational()); - } - return left; - } - - function additive() { - var left = multiplicative(); - var token; - while ((token = expect('+','-'))) { - left = binaryFn(left, token.fn, multiplicative()); - } - return left; - } - - function multiplicative() { - var left = unary(); - var token; - while ((token = expect('*','/','%'))) { - left = binaryFn(left, token.fn, unary()); - } - return left; - } - - function unary() { - var token; - if (expect('+')) { - return primary(); - } else if ((token = expect('-'))) { - return binaryFn(ZERO, token.fn, unary()); - } else if ((token = expect('!'))) { - return unaryFn(token.fn, unary()); - } else { - return primary(); - } - } - - - function primary() { - var primary; - if (expect('(')) { - primary = filterChain(); - consume(')'); - } else if (expect('[')) { - primary = arrayDeclaration(); - } else if (expect('{')) { - primary = object(); - } else { - var token = expect(); - primary = token.fn; - if (!primary) { - throwError("not a primary expression", token); - } - } - - var next, context; - while ((next = expect('(', '[', '.'))) { - if (next.text === '(') { - primary = functionCall(primary, context); - context = null; - } else if (next.text === '[') { - context = primary; - primary = objectIndex(primary); - } else if (next.text === '.') { - context = primary; - primary = fieldAccess(primary); - } else { - throwError("IMPOSSIBLE"); - } - } - return primary; - } - - function _fieldAccess(object) { - var field = expect().text; - var getter = getterFn(field, csp); - return extend( - function(scope, locals, self) { - return getter(self || object(scope, locals), locals); - }, - { - assign:function(scope, value, locals) { - return setter(object(scope, locals), field, value); - } - } - ); - } - - function _objectIndex(obj) { - var indexFn = expression(); - consume(']'); - return extend( - function(self, locals){ - var o = obj(self, locals), - i = indexFn(self, locals), - v, p; - - if (!o) return undefined; - v = o[i]; - if (v && v.then) { - p = v; - if (!('$$v' in v)) { - p.$$v = undefined; - p.then(function(val) { p.$$v = val; }); - } - v = v.$$v; - } - return v; - }, { - assign:function(self, value, locals){ - return obj(self, locals)[indexFn(self, locals)] = value; - } - }); - } - - function _functionCall(fn, contextGetter) { - var argsFn = []; - if (peekToken().text != ')') { - do { - argsFn.push(expression()); - } while (expect(',')); - } - consume(')'); - return function(scope, locals){ - var args = [], - context = contextGetter ? contextGetter(scope, locals) : scope; - - for ( var i = 0; i < argsFn.length; i++) { - args.push(argsFn[i](scope, locals)); - } - var fnPtr = fn(scope, locals, context) || noop; - // IE stupidity! - return fnPtr.apply - ? fnPtr.apply(context, args) - : fnPtr(args[0], args[1], args[2], args[3], args[4]); - }; - } - - // This is used with json array declaration - function arrayDeclaration () { - var elementFns = []; - if (peekToken().text != ']') { - do { - elementFns.push(expression()); - } while (expect(',')); - } - consume(']'); - return function(self, locals){ - var array = []; - for ( var i = 0; i < elementFns.length; i++) { - array.push(elementFns[i](self, locals)); - } - return array; - }; - } - - function object () { - var keyValues = []; - if (peekToken().text != '}') { - do { - var token = expect(), - key = token.string || token.text; - consume(":"); - var value = expression(); - keyValues.push({key:key, value:value}); - } while (expect(',')); - } - consume('}'); - return function(self, locals){ - var object = {}; - for ( var i = 0; i < keyValues.length; i++) { - var keyValue = keyValues[i]; - object[keyValue.key] = keyValue.value(self, locals); - } - return object; - }; - } -} - -////////////////////////////////////////////////// -// Parser helper functions -////////////////////////////////////////////////// - -function setter(obj, path, setValue) { - var element = path.split('.'); - for (var i = 0; element.length > 1; i++) { - var key = element.shift(); - var propertyObj = obj[key]; - if (!propertyObj) { - propertyObj = {}; - obj[key] = propertyObj; - } - obj = propertyObj; - } - obj[element.shift()] = setValue; - return setValue; -} - -/** - * Return the value accesible from the object by path. Any undefined traversals are ignored - * @param {Object} obj starting object - * @param {string} path path to traverse - * @param {boolean=true} bindFnToScope - * @returns value as accesbile by path - */ -//TODO(misko): this function needs to be removed -function getter(obj, path, bindFnToScope) { - if (!path) return obj; - var keys = path.split('.'); - var key; - var lastInstance = obj; - var len = keys.length; - - for (var i = 0; i < len; i++) { - key = keys[i]; - if (obj) { - obj = (lastInstance = obj)[key]; - } - } - if (!bindFnToScope && isFunction(obj)) { - return bind(lastInstance, obj); - } - return obj; -} - -var getterFnCache = {}; - -/** - * Implementation of the "Black Hole" variant from: - * - http://jsperf.com/angularjs-parse-getter/4 - * - http://jsperf.com/path-evaluation-simplified/7 - */ -function cspSafeGetterFn(key0, key1, key2, key3, key4) { - return function(scope, locals) { - var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope, - promise; - - if (pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key0]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key1 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key1]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key2 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key2]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key3 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key3]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key4 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key4]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - return pathVal; - }; -} - -function getterFn(path, csp) { - if (getterFnCache.hasOwnProperty(path)) { - return getterFnCache[path]; - } - - var pathKeys = path.split('.'), - pathKeysLength = pathKeys.length, - fn; - - if (csp) { - fn = (pathKeysLength < 6) - ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4]) - : function(scope, locals) { - var i = 0, val; - do { - val = cspSafeGetterFn( - pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++] - )(scope, locals); - - locals = undefined; // clear after first iteration - scope = val; - } while (i < pathKeysLength); - return val; - } - } else { - var code = 'var l, fn, p;\n'; - forEach(pathKeys, function(key, index) { - code += 'if(s === null || s === undefined) return s;\n' + - 'l=s;\n' + - 's='+ (index - // we simply dereference 's' on any .dot notation - ? 's' - // but if we are first then we check locals first, and if so read it first - : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' + - 'if (s && s.then) {\n' + - ' if (!("$$v" in s)) {\n' + - ' p=s;\n' + - ' p.$$v = undefined;\n' + - ' p.then(function(v) {p.$$v=v;});\n' + - '}\n' + - ' s=s.$$v\n' + - '}\n'; - }); - code += 'return s;'; - fn = Function('s', 'k', code); // s=scope, k=locals - fn.toString = function() { return code; }; - } - - return getterFnCache[path] = fn; -} - -/////////////////////////////////// - -/** - * @ngdoc function - * @name ng.$parse - * @function - * - * @description - * - * Converts Angular {@link guide/expression expression} into a function. - * - *
- *   var getter = $parse('user.name');
- *   var setter = getter.assign;
- *   var context = {user:{name:'angular'}};
- *   var locals = {user:{name:'local'}};
- *
- *   expect(getter(context)).toEqual('angular');
- *   setter(context, 'newValue');
- *   expect(context.user.name).toEqual('newValue');
- *   expect(getter(context, locals)).toEqual('local');
- * 
- * - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (tipically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - * - * The return function also has an `assign` property, if the expression is assignable, which - * allows one to set values to expressions. - * - */ -function $ParseProvider() { - var cache = {}; - this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { - return function(exp) { - switch(typeof exp) { - case 'string': - return cache.hasOwnProperty(exp) - ? cache[exp] - : cache[exp] = parser(exp, false, $filter, $sniffer.csp); - case 'function': - return exp; - default: - return noop; - } - }; - }]; -} - -/** - * @ngdoc service - * @name ng.$q - * @requires $rootScope - * - * @description - * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q). - * - * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an - * interface for interacting with an object that represents the result of an action that is - * performed asynchronously, and may or may not be finished at any given point in time. - * - * From the perspective of dealing with error handling, deferred and promise APIs are to - * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. - * - *
- *   // for the purpose of this example let's assume that variables `$q` and `scope` are
- *   // available in the current lexical scope (they could have been injected or passed in).
- *
- *   function asyncGreet(name) {
- *     var deferred = $q.defer();
- *
- *     setTimeout(function() {
- *       // since this fn executes async in a future turn of the event loop, we need to wrap
- *       // our code into an $apply call so that the model changes are properly observed.
- *       scope.$apply(function() {
- *         if (okToGreet(name)) {
- *           deferred.resolve('Hello, ' + name + '!');
- *         } else {
- *           deferred.reject('Greeting ' + name + ' is not allowed.');
- *         }
- *       });
- *     }, 1000);
- *
- *     return deferred.promise;
- *   }
- *
- *   var promise = asyncGreet('Robin Hood');
- *   promise.then(function(greeting) {
- *     alert('Success: ' + greeting);
- *   }, function(reason) {
- *     alert('Failed: ' + reason);
- *   });
- * 
- * - * At first it might not be obvious why this extra complexity is worth the trouble. The payoff - * comes in the way of - * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md). - * - * Additionally the promise api allows for composition that is very hard to do with the - * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. - * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the - * section on serial or parallel joining of promises. - * - * - * # The Deferred API - * - * A new instance of deferred is constructed by calling `$q.defer()`. - * - * The purpose of the deferred object is to expose the associated Promise instance as well as APIs - * that can be used for signaling the successful or unsuccessful completion of the task. - * - * **Methods** - * - * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection - * constructed via `$q.reject`, the promise will be rejected instead. - * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to - * resolving it with a rejection constructed via `$q.reject`. - * - * **Properties** - * - * - promise – `{Promise}` – promise object associated with this deferred. - * - * - * # The Promise API - * - * A new promise instance is created when a deferred instance is created and can be retrieved by - * calling `deferred.promise`. - * - * The purpose of the promise object is to allow for interested parties to get access to the result - * of the deferred task when it completes. - * - * **Methods** - * - * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved - * or rejected calls one of the success or error callbacks asynchronously as soon as the result - * is available. The callbacks are called with a single argument the result or rejection reason. - * - * This method *returns a new promise* which is resolved or rejected via the return value of the - * `successCallback` or `errorCallback`. - * - * - * # Chaining promises - * - * Because calling `then` api of a promise returns a new derived promise, it is easily possible - * to create a chain of promises: - * - *
- *   promiseB = promiseA.then(function(result) {
- *     return result + 1;
- *   });
- *
- *   // promiseB will be resolved immediately after promiseA is resolved and its value will be
- *   // the result of promiseA incremented by 1
- * 
- * - * It is possible to create chains of any length and since a promise can be resolved with another - * promise (which will defer its resolution further), it is possible to pause/defer resolution of - * the promises at any point in the chain. This makes it possible to implement powerful apis like - * $http's response interceptors. - * - * - * # Differences between Kris Kowal's Q and $q - * - * There are three main differences: - * - * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation - * mechanism in angular, which means faster propagation of resolution or rejection into your - * models and avoiding unnecessary browser repaints, which would result in flickering UI. - * - $q promises are recognized by the templating engine in angular, which means that in templates - * you can treat promises attached to a scope as if they were the resulting values. - * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains - * all the important functionality needed for common async tasks. - * - * # Testing - * - *
- *    it('should simulate promise', inject(function($q, $rootScope) {
- *      var deferred = $q.defer();
- *      var promise = deferred.promise;
- *      var resolvedValue;
- * 
- *      promise.then(function(value) { resolvedValue = value; });
- *      expect(resolvedValue).toBeUndefined();
- * 
- *      // Simulate resolving of promise
- *      deferred.resolve(123);
- *      // Note that the 'then' function does not get called synchronously.
- *      // This is because we want the promise API to always be async, whether or not
- *      // it got called synchronously or asynchronously.
- *      expect(resolvedValue).toBeUndefined();
- * 
- *      // Propagate promise resolution to 'then' functions using $apply().
- *      $rootScope.$apply();
- *      expect(resolvedValue).toEqual(123);
- *    });
- *  
- */ -function $QProvider() { - - this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler); - }]; -} - - -/** - * Constructs a promise manager. - * - * @param {function(function)} nextTick Function for executing functions in the next turn. - * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for - * debugging purposes. - * @returns {object} Promise manager. - */ -function qFactory(nextTick, exceptionHandler) { - - /** - * @ngdoc - * @name ng.$q#defer - * @methodOf ng.$q - * @description - * Creates a `Deferred` object which represents a task which will finish in the future. - * - * @returns {Deferred} Returns a new instance of deferred. - */ - var defer = function() { - var pending = [], - value, deferred; - - deferred = { - - resolve: function(val) { - if (pending) { - var callbacks = pending; - pending = undefined; - value = ref(val); - - if (callbacks.length) { - nextTick(function() { - var callback; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - callback = callbacks[i]; - value.then(callback[0], callback[1]); - } - }); - } - } - }, - - - reject: function(reason) { - deferred.resolve(reject(reason)); - }, - - - promise: { - then: function(callback, errback) { - var result = defer(); - - var wrappedCallback = function(value) { - try { - result.resolve((callback || defaultCallback)(value)); - } catch(e) { - exceptionHandler(e); - result.reject(e); - } - }; - - var wrappedErrback = function(reason) { - try { - result.resolve((errback || defaultErrback)(reason)); - } catch(e) { - exceptionHandler(e); - result.reject(e); - } - }; - - if (pending) { - pending.push([wrappedCallback, wrappedErrback]); - } else { - value.then(wrappedCallback, wrappedErrback); - } - - return result.promise; - } - } - }; - - return deferred; - }; - - - var ref = function(value) { - if (value && value.then) return value; - return { - then: function(callback) { - var result = defer(); - nextTick(function() { - result.resolve(callback(value)); - }); - return result.promise; - } - }; - }; - - - /** - * @ngdoc - * @name ng.$q#reject - * @methodOf ng.$q - * @description - * Creates a promise that is resolved as rejected with the specified `reason`. This api should be - * used to forward rejection in a chain of promises. If you are dealing with the last promise in - * a promise chain, you don't need to worry about it. - * - * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of - * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via - * a promise error callback and you want to forward the error to the promise derived from the - * current promise, you have to "rethrow" the error by returning a rejection constructed via - * `reject`. - * - *
-   *   promiseB = promiseA.then(function(result) {
-   *     // success: do something and resolve promiseB
-   *     //          with the old or a new result
-   *     return result;
-   *   }, function(reason) {
-   *     // error: handle the error if possible and
-   *     //        resolve promiseB with newPromiseOrValue,
-   *     //        otherwise forward the rejection to promiseB
-   *     if (canHandle(reason)) {
-   *      // handle the error and recover
-   *      return newPromiseOrValue;
-   *     }
-   *     return $q.reject(reason);
-   *   });
-   * 
- * - * @param {*} reason Constant, message, exception or an object representing the rejection reason. - * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. - */ - var reject = function(reason) { - return { - then: function(callback, errback) { - var result = defer(); - nextTick(function() { - result.resolve((errback || defaultErrback)(reason)); - }); - return result.promise; - } - }; - }; - - - /** - * @ngdoc - * @name ng.$q#when - * @methodOf ng.$q - * @description - * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. - * This is useful when you are dealing with an object that might or might not be a promise, or if - * the promise comes from a source that can't be trusted. - * - * @param {*} value Value or a promise - * @returns {Promise} Returns a promise of the passed value or promise - */ - var when = function(value, callback, errback) { - var result = defer(), - done; - - var wrappedCallback = function(value) { - try { - return (callback || defaultCallback)(value); - } catch (e) { - exceptionHandler(e); - return reject(e); - } - }; - - var wrappedErrback = function(reason) { - try { - return (errback || defaultErrback)(reason); - } catch (e) { - exceptionHandler(e); - return reject(e); - } - }; - - nextTick(function() { - ref(value).then(function(value) { - if (done) return; - done = true; - result.resolve(ref(value).then(wrappedCallback, wrappedErrback)); - }, function(reason) { - if (done) return; - done = true; - result.resolve(wrappedErrback(reason)); - }); - }); - - return result.promise; - }; - - - function defaultCallback(value) { - return value; - } - - - function defaultErrback(reason) { - return reject(reason); - } - - - /** - * @ngdoc - * @name ng.$q#all - * @methodOf ng.$q - * @description - * Combines multiple promises into a single promise that is resolved when all of the input - * promises are resolved. - * - * @param {Array.} promises An array of promises. - * @returns {Promise} Returns a single promise that will be resolved with an array of values, - * each value corresponding to the promise at the same index in the `promises` array. If any of - * the promises is resolved with a rejection, this resulting promise will be resolved with the - * same rejection. - */ - function all(promises) { - var deferred = defer(), - counter = promises.length, - results = []; - - if (counter) { - forEach(promises, function(promise, index) { - ref(promise).then(function(value) { - if (index in results) return; - results[index] = value; - if (!(--counter)) deferred.resolve(results); - }, function(reason) { - if (index in results) return; - deferred.reject(reason); - }); - }); - } else { - deferred.resolve(results); - } - - return deferred.promise; - } - - return { - defer: defer, - reject: reject, - when: when, - all: all - }; -} - -/** - * @ngdoc object - * @name ng.$routeProvider - * @function - * - * @description - * - * Used for configuring routes. See {@link ng.$route $route} for an example. - */ -function $RouteProvider(){ - var routes = {}; - - /** - * @ngdoc method - * @name ng.$routeProvider#when - * @methodOf ng.$routeProvider - * - * @param {string} path Route path (matched against `$location.path`). If `$location.path` - * contains redundant trailing slash or is missing one, the route will still match and the - * `$location.path` will be updated to add or drop the trailing slash to exactly match the - * route definition. - * - * `path` can contain named groups starting with a colon (`:name`). All characters up to the - * next slash are matched and stored in `$routeParams` under the given `name` when the route - * matches. - * - * @param {Object} route Mapping information to be assigned to `$route.current` on route - * match. - * - * Object properties: - * - * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly - * created scope or the name of a {@link angular.Module#controller registered controller} - * if passed as a string. - * - `template` – `{string=}` – html template as a string that should be used by - * {@link ng.directive:ngView ngView} or - * {@link ng.directive:ngInclude ngInclude} directives. - * this property takes precedence over `templateUrl`. - * - `templateUrl` – `{string=}` – path to an html template that should be used by - * {@link ng.directive:ngView ngView}. - * - `resolve` - `{Object.=}` - An optional map of dependencies which should - * be injected into the controller. If any of these dependencies are promises, they will be - * resolved and converted to a value before the controller is instantiated and the - * `$routeChangeSuccess` event is fired. The map object is: - * - * - `key` – `{string}`: a name of a dependency to be injected into the controller. - * - `factory` - `{string|function}`: If `string` then it is an alias for a service. - * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} - * and the return value is treated as the dependency. If the result is a promise, it is resolved - * before its value is injected into the controller. - * - * - `redirectTo` – {(string|function())=} – value to update - * {@link ng.$location $location} path with and trigger route redirection. - * - * If `redirectTo` is a function, it will be called with the following parameters: - * - * - `{Object.}` - route parameters extracted from the current - * `$location.path()` by applying the current route templateUrl. - * - `{string}` - current `$location.path()` - * - `{Object}` - current `$location.search()` - * - * The custom `redirectTo` function is expected to return a string which will be used - * to update `$location.path()` and `$location.search()`. - * - * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search() - * changes. - * - * If the option is set to `false` and url in the browser changes, then - * `$routeUpdate` event is broadcasted on the root scope. - * - * @returns {Object} self - * - * @description - * Adds a new route definition to the `$route` service. - */ - this.when = function(path, route) { - routes[path] = extend({reloadOnSearch: true}, route); - - // create redirection for trailing slashes - if (path) { - var redirectPath = (path[path.length-1] == '/') - ? path.substr(0, path.length-1) - : path +'/'; - - routes[redirectPath] = {redirectTo: path}; - } - - return this; - }; - - /** - * @ngdoc method - * @name ng.$routeProvider#otherwise - * @methodOf ng.$routeProvider - * - * @description - * Sets route definition that will be used on route change when no other route definition - * is matched. - * - * @param {Object} params Mapping information to be assigned to `$route.current`. - * @returns {Object} self - */ - this.otherwise = function(params) { - this.when(null, params); - return this; - }; - - - this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache', - function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache) { - - /** - * @ngdoc object - * @name ng.$route - * @requires $location - * @requires $routeParams - * - * @property {Object} current Reference to the current route definition. - * The route definition contains: - * - * - `controller`: The controller constructor as define in route definition. - * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for - * controller instantiation. The `locals` contain - * the resolved values of the `resolve` map. Additionally the `locals` also contain: - * - * - `$scope` - The current route scope. - * - `$template` - The current route template HTML. - * - * @property {Array.} routes Array of all configured routes. - * - * @description - * Is used for deep-linking URLs to controllers and views (HTML partials). - * It watches `$location.url()` and tries to map the path to an existing route definition. - * - * You can define routes through {@link ng.$routeProvider $routeProvider}'s API. - * - * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView} - * directive and the {@link ng.$routeParams $routeParams} service. - * - * @example - This example shows how changing the URL hash causes the `$route` to match a route against the - URL, and the `ngView` pulls in the partial. - - Note that this example is using {@link ng.directive:script inlined templates} - to get it working on jsfiddle as well. - - - -
- Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
- -
-
- -
$location.path() = {{$location.path()}}
-
$route.current.templateUrl = {{$route.current.templateUrl}}
-
$route.current.params = {{$route.current.params}}
-
$route.current.scope.name = {{$route.current.scope.name}}
-
$routeParams = {{$routeParams}}
-
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
- Chapter Id: {{params.chapterId}} -
- - - angular.module('ngView', [], function($routeProvider, $locationProvider) { - $routeProvider.when('/Book/:bookId', { - templateUrl: 'book.html', - controller: BookCntl, - resolve: { - // I will cause a 1 second delay - delay: function($q, $timeout) { - var delay = $q.defer(); - $timeout(delay.resolve, 1000); - return delay.promise; - } - } - }); - $routeProvider.when('/Book/:bookId/ch/:chapterId', { - templateUrl: 'chapter.html', - controller: ChapterCntl - }); - - // configure html5 to get links working on jsfiddle - $locationProvider.html5Mode(true); - }); - - function MainCntl($scope, $route, $routeParams, $location) { - $scope.$route = $route; - $scope.$location = $location; - $scope.$routeParams = $routeParams; - } - - function BookCntl($scope, $routeParams) { - $scope.name = "BookCntl"; - $scope.params = $routeParams; - } - - function ChapterCntl($scope, $routeParams) { - $scope.name = "ChapterCntl"; - $scope.params = $routeParams; - } - - - - it('should load and compile correct template', function() { - element('a:contains("Moby: Ch1")').click(); - var content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: ChapterCntl/); - expect(content).toMatch(/Book Id\: Moby/); - expect(content).toMatch(/Chapter Id\: 1/); - - element('a:contains("Scarlet")').click(); - sleep(2); // promises are not part of scenario waiting - content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: BookCntl/); - expect(content).toMatch(/Book Id\: Scarlet/); - }); - -
- */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeStart - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted before a route change. At this point the route services starts - * resolving all of the dependencies needed for the route change to occurs. - * Typically this involves fetching the view template as well as any dependencies - * defined in `resolve` route property. Once all of the dependencies are resolved - * `$routeChangeSuccess` is fired. - * - * @param {Route} next Future route information. - * @param {Route} current Current route information. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeSuccess - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted after a route dependencies are resolved. - * {@link ng.directive:ngView ngView} listens for the directive - * to instantiate the controller and render the view. - * - * @param {Object} angularEvent Synthetic event object. - * @param {Route} current Current route information. - * @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeError - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted if any of the resolve promises are rejected. - * - * @param {Route} current Current route information. - * @param {Route} previous Previous route information. - * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeUpdate - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * - * The `reloadOnSearch` property has been set to false, and we are reusing the same - * instance of the Controller. - */ - - var forceReload = false, - $route = { - routes: routes, - - /** - * @ngdoc method - * @name ng.$route#reload - * @methodOf ng.$route - * - * @description - * Causes `$route` service to reload the current route even if - * {@link ng.$location $location} hasn't changed. - * - * As a result of that, {@link ng.directive:ngView ngView} - * creates new scope, reinstantiates the controller. - */ - reload: function() { - forceReload = true; - $rootScope.$evalAsync(updateRoute); - } - }; - - $rootScope.$on('$locationChangeSuccess', updateRoute); - - return $route; - - ///////////////////////////////////////////////////// - - /** - * @param on {string} current url - * @param when {string} route when template to match the url against - * @return {?Object} - */ - function switchRouteMatcher(on, when) { - // TODO(i): this code is convoluted and inefficient, we should construct the route matching - // regex only once and then reuse it - - // Escape regexp special characters. - when = '^' + when.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + '$'; - var regex = '', - params = [], - dst = {}; - - var re = /:(\w+)/g, - paramMatch, - lastMatchedIndex = 0; - - while ((paramMatch = re.exec(when)) !== null) { - // Find each :param in `when` and replace it with a capturing group. - // Append all other sections of when unchanged. - regex += when.slice(lastMatchedIndex, paramMatch.index); - regex += '([^\\/]*)'; - params.push(paramMatch[1]); - lastMatchedIndex = re.lastIndex; - } - // Append trailing path part. - regex += when.substr(lastMatchedIndex); - - var match = on.match(new RegExp(regex)); - if (match) { - forEach(params, function(name, index) { - dst[name] = match[index + 1]; - }); - } - return match ? dst : null; - } - - function updateRoute() { - var next = parseRoute(), - last = $route.current; - - if (next && last && next.$$route === last.$$route - && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { - last.params = next.params; - copy(last.params, $routeParams); - $rootScope.$broadcast('$routeUpdate', last); - } else if (next || last) { - forceReload = false; - $rootScope.$broadcast('$routeChangeStart', next, last); - $route.current = next; - if (next) { - if (next.redirectTo) { - if (isString(next.redirectTo)) { - $location.path(interpolate(next.redirectTo, next.params)).search(next.params) - .replace(); - } else { - $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) - .replace(); - } - } - } - - $q.when(next). - then(function() { - if (next) { - var keys = [], - values = [], - template; - - forEach(next.resolve || {}, function(value, key) { - keys.push(key); - values.push(isString(value) ? $injector.get(value) : $injector.invoke(value)); - }); - if (isDefined(template = next.template)) { - } else if (isDefined(template = next.templateUrl)) { - template = $http.get(template, {cache: $templateCache}). - then(function(response) { return response.data; }); - } - if (isDefined(template)) { - keys.push('$template'); - values.push(template); - } - return $q.all(values).then(function(values) { - var locals = {}; - forEach(values, function(value, index) { - locals[keys[index]] = value; - }); - return locals; - }); - } - }). - // after route change - then(function(locals) { - if (next == $route.current) { - if (next) { - next.locals = locals; - copy(next.params, $routeParams); - } - $rootScope.$broadcast('$routeChangeSuccess', next, last); - } - }, function(error) { - if (next == $route.current) { - $rootScope.$broadcast('$routeChangeError', next, last, error); - } - }); - } - } - - - /** - * @returns the current active route, by matching it against the URL - */ - function parseRoute() { - // Match a route - var params, match; - forEach(routes, function(route, path) { - if (!match && (params = switchRouteMatcher($location.path(), path))) { - match = inherit(route, { - params: extend({}, $location.search(), params), - pathParams: params}); - match.$$route = route; - } - }); - // No route matched; fallback to "otherwise" route - return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); - } - - /** - * @returns interpolation of the redirect path with the parametrs - */ - function interpolate(string, params) { - var result = []; - forEach((string||'').split(':'), function(segment, i) { - if (i == 0) { - result.push(segment); - } else { - var segmentMatch = segment.match(/(\w+)(.*)/); - var key = segmentMatch[1]; - result.push(params[key]); - result.push(segmentMatch[2] || ''); - delete params[key]; - } - }); - return result.join(''); - } - }]; -} - -/** - * @ngdoc object - * @name ng.$routeParams - * @requires $route - * - * @description - * Current set of route parameters. The route parameters are a combination of the - * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters - * are extracted when the {@link ng.$route $route} path is matched. - * - * In case of parameter name collision, `path` params take precedence over `search` params. - * - * The service guarantees that the identity of the `$routeParams` object will remain unchanged - * (but its properties will likely change) even when a route change occurs. - * - * @example - *
- *  // Given:
- *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
- *  // Route: /Chapter/:chapterId/Section/:sectionId
- *  //
- *  // Then
- *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
- * 
- */ -function $RouteParamsProvider() { - this.$get = valueFn({}); -} - -/** - * DESIGN NOTES - * - * The design decisions behind the scope are heavily favored for speed and memory consumption. - * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. - * - * Closures construction is expensive in terms of speed as well as memory: - * - No closures, instead use prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties - * - * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add - * items to the array at the beginning (shift) instead of at the end (push) - * - * Child scopes are created and removed often - * - Using an array would be slow since inserts in middle are expensive so we use linked list - * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. - */ - - -/** - * @ngdoc object - * @name ng.$rootScopeProvider - * @description - * - * Provider for the $rootScope service. - */ - -/** - * @ngdoc function - * @name ng.$rootScopeProvider#digestTtl - * @methodOf ng.$rootScopeProvider - * @description - * - * Sets the number of digest iterations the scope should attempt to execute before giving up and - * assuming that the model is unstable. - * - * The current default is 10 iterations. - * - * @param {number} limit The number of digest iterations. - */ - - -/** - * @ngdoc object - * @name ng.$rootScope - * @description - * - * Every application has a single root {@link ng.$rootScope.Scope scope}. - * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide - * event processing life-cycle. See {@link guide/scope developer guide on scopes}. - */ -function $RootScopeProvider(){ - var TTL = 10; - - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; - - this.$get = ['$injector', '$exceptionHandler', '$parse', - function( $injector, $exceptionHandler, $parse) { - - /** - * @ngdoc function - * @name ng.$rootScope.Scope - * - * @description - * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the - * {@link AUTO.$injector $injector}. Child scopes are created using the - * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) - * - * Here is a simple scope snippet to show how you can interact with the scope. - *
-        angular.injector(['ng']).invoke(function($rootScope) {
-           var scope = $rootScope.$new();
-           scope.salutation = 'Hello';
-           scope.name = 'World';
-
-           expect(scope.greeting).toEqual(undefined);
-
-           scope.$watch('name', function() {
-             scope.greeting = scope.salutation + ' ' + scope.name + '!';
-           }); // initialize the watch
-
-           expect(scope.greeting).toEqual(undefined);
-           scope.name = 'Misko';
-           // still old value, since watches have not been called yet
-           expect(scope.greeting).toEqual(undefined);
-
-           scope.$digest(); // fire all  the watches
-           expect(scope.greeting).toEqual('Hello Misko!');
-        });
-     * 
- * - * # Inheritance - * A scope can inherit from a parent scope, as in this example: - *
-         var parent = $rootScope;
-         var child = parent.$new();
-
-         parent.salutation = "Hello";
-         child.name = "World";
-         expect(child.salutation).toEqual('Hello');
-
-         child.salutation = "Welcome";
-         expect(child.salutation).toEqual('Welcome');
-         expect(parent.salutation).toEqual('Hello');
-     * 
- * - * - * @param {Object.=} providers Map of service factory which need to be provided - * for the current scope. Defaults to {@link ng}. - * @param {Object.=} instanceCache Provides pre-instantiated services which should - * append/override services provided by `providers`. This is handy when unit-testing and having - * the need to override a default service. - * @returns {Object} Newly created scope. - * - */ - function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = - this.$$nextSibling = this.$$prevSibling = - this.$$childHead = this.$$childTail = null; - this['this'] = this.$root = this; - this.$$destroyed = false; - this.$$asyncQueue = []; - this.$$listeners = {}; - this.$$isolateBindings = {}; - } - - /** - * @ngdoc property - * @name ng.$rootScope.Scope#$id - * @propertyOf ng.$rootScope.Scope - * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for - * debugging. - */ - - - Scope.prototype = { - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$new - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Creates a new child {@link ng.$rootScope.Scope scope}. - * - * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and - * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope - * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. - * - * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for - * the scope and its child scopes to be permanently detached from the parent and thus stop - * participating in model change detection and listener notification by invoking. - * - * @param {boolean} isolate if true then the scope does not prototypically inherit from the - * parent scope. The scope is isolated, as it can not see parent scope properties. - * When creating widgets it is useful for the widget to not accidentally read parent - * state. - * - * @returns {Object} The newly created child scope. - * - */ - $new: function(isolate) { - var Child, - child; - - if (isFunction(isolate)) { - // TODO: remove at some point - throw Error('API-CHANGE: Use $controller to instantiate controllers.'); - } - if (isolate) { - child = new Scope(); - child.$root = this.$root; - } else { - Child = function() {}; // should be anonymous; This is so that when the minifier munges - // the name it does not become random set of chars. These will then show up as class - // name in the debugger. - Child.prototype = this; - child = new Child(); - child.$id = nextUid(); - } - child['this'] = child; - child.$$listeners = {}; - child.$parent = this; - child.$$asyncQueue = []; - child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null; - child.$$prevSibling = this.$$childTail; - if (this.$$childHead) { - this.$$childTail.$$nextSibling = child; - this.$$childTail = child; - } else { - this.$$childHead = this.$$childTail = child; - } - return child; - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$watch - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Registers a `listener` callback to be executed whenever the `watchExpression` changes. - * - * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and - * should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()} - * reruns when it detects changes the `watchExpression` can execute multiple times per - * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) - * - The `listener` is called only when the value from the current `watchExpression` and the - * previous call to `watchExpression` are not equal (with the exception of the initial run, - * see below). The inequality is determined according to - * {@link angular.equals} function. To save the value of the object for later comparison, the - * {@link angular.copy} function is used. It also means that watching complex options will - * have adverse memory and performance implications. - * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This - * is achieved by rerunning the watchers until no changes are detected. The rerun iteration - * limit is 10 to prevent an infinite loop deadlock. - * - * - * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, - * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` - * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is - * detected, be prepared for multiple calls to your listener.) - * - * After a watcher is registered with the scope, the `listener` fn is called asynchronously - * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the - * watcher. In rare cases, this is undesirable because the listener is called when the result - * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you - * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the - * listener was called due to initialization. - * - * - * # Example - *
-           // let's assume that scope was dependency injected as the $rootScope
-           var scope = $rootScope;
-           scope.name = 'misko';
-           scope.counter = 0;
-
-           expect(scope.counter).toEqual(0);
-           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });
-           expect(scope.counter).toEqual(0);
-
-           scope.$digest();
-           // no variable change
-           expect(scope.counter).toEqual(0);
-
-           scope.name = 'adam';
-           scope.$digest();
-           expect(scope.counter).toEqual(1);
-       * 
- * - * - * - * @param {(function()|string)} watchExpression Expression that is evaluated on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a - * call to the `listener`. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(scope)`: called with current `scope` as a parameter. - * @param {(function()|string)=} listener Callback called whenever the return value of - * the `watchExpression` changes. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(newValue, oldValue, scope)`: called with current and previous values as parameters. - * - * @param {boolean=} objectEquality Compare object for equality rather than for reference. - * @returns {function()} Returns a deregistration function for this listener. - */ - $watch: function(watchExp, listener, objectEquality) { - var scope = this, - get = compileToFn(watchExp, 'watch'), - array = scope.$$watchers, - watcher = { - fn: listener, - last: initWatchVal, - get: get, - exp: watchExp, - eq: !!objectEquality - }; - - // in the case user pass string, we need to compile it, do we really need this ? - if (!isFunction(listener)) { - var listenFn = compileToFn(listener || noop, 'listener'); - watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);}; - } - - if (!array) { - array = scope.$$watchers = []; - } - // we use unshift since we use a while loop in $digest for speed. - // the while loop reads in reverse order. - array.unshift(watcher); - - return function() { - arrayRemove(array, watcher); - }; - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$digest - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children. - * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the - * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are - * firing. This means that it is possible to get into an infinite loop. This function will throw - * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10. - * - * Usually you don't call `$digest()` directly in - * {@link ng.directive:ngController controllers} or in - * {@link ng.$compileProvider#directive directives}. - * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a - * {@link ng.$compileProvider#directive directives}) will force a `$digest()`. - * - * If you want to be notified whenever `$digest()` is called, - * you can register a `watchExpression` function with {@link ng.$rootScope.Scope#$watch $watch()} - * with no `listener`. - * - * You may have a need to call `$digest()` from within unit-tests, to simulate the scope - * life-cycle. - * - * # Example - *
-           var scope = ...;
-           scope.name = 'misko';
-           scope.counter = 0;
-
-           expect(scope.counter).toEqual(0);
-           scope.$watch('name', function(newValue, oldValue) {
-             scope.counter = scope.counter + 1;
-           });
-           expect(scope.counter).toEqual(0);
-
-           scope.$digest();
-           // no variable change
-           expect(scope.counter).toEqual(0);
-
-           scope.name = 'adam';
-           scope.$digest();
-           expect(scope.counter).toEqual(1);
-       * 
- * - */ - $digest: function() { - var watch, value, last, - watchers, - asyncQueue, - length, - dirty, ttl = TTL, - next, current, target = this, - watchLog = [], - logIdx, logMsg; - - beginPhase('$digest'); - - do { - dirty = false; - current = target; - do { - asyncQueue = current.$$asyncQueue; - while(asyncQueue.length) { - try { - current.$eval(asyncQueue.shift()); - } catch (e) { - $exceptionHandler(e); - } - } - if ((watchers = current.$$watchers)) { - // process our watches - length = watchers.length; - while (length--) { - try { - watch = watchers[length]; - // Most common watches are on primitives, in which case we can short - // circuit it with === operator, only when === fails do we use .equals - if ((value = watch.get(current)) !== (last = watch.last) && - !(watch.eq - ? equals(value, last) - : (typeof value == 'number' && typeof last == 'number' - && isNaN(value) && isNaN(last)))) { - dirty = true; - watch.last = watch.eq ? copy(value) : value; - watch.fn(value, ((last === initWatchVal) ? value : last), current); - if (ttl < 5) { - logIdx = 4 - ttl; - if (!watchLog[logIdx]) watchLog[logIdx] = []; - logMsg = (isFunction(watch.exp)) - ? 'fn: ' + (watch.exp.name || watch.exp.toString()) - : watch.exp; - logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last); - watchLog[logIdx].push(logMsg); - } - } - } catch (e) { - $exceptionHandler(e); - } - } - } - - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $broadcast - if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) { - while(current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while ((current = next)); - - if(dirty && !(ttl--)) { - clearPhase(); - throw Error(TTL + ' $digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: ' + toJson(watchLog)); - } - } while (dirty || asyncQueue.length); - - clearPhase(); - }, - - - /** - * @ngdoc event - * @name ng.$rootScope.Scope#$destroy - * @eventOf ng.$rootScope.Scope - * @eventType broadcast on scope being destroyed - * - * @description - * Broadcasted when a scope and its children are being destroyed. - */ - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$destroy - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Removes the current scope (and all of its children) from the parent scope. Removal implies - * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer - * propagate to the current scope and its children. Removal also implies that the current - * scope is eligible for garbage collection. - * - * The `$destroy()` is usually used by directives such as - * {@link ng.directive:ngRepeat ngRepeat} for managing the - * unrolling of the loop. - * - * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope. - * Application code can register a `$destroy` event handler that will give it chance to - * perform any necessary cleanup. - */ - $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed - if ($rootScope == this || this.$$destroyed) return; - var parent = this.$parent; - - this.$broadcast('$destroy'); - this.$$destroyed = true; - - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; - - // This is bogus code that works around Chrome's GC leak - // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 - this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = - this.$$childTail = null; - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$eval - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Executes the `expression` on the current scope returning the result. Any exceptions in the - * expression are propagated (uncaught). This is useful when evaluating Angular expressions. - * - * # Example - *
-           var scope = ng.$rootScope.Scope();
-           scope.a = 1;
-           scope.b = 2;
-
-           expect(scope.$eval('a+b')).toEqual(3);
-           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
-       * 
- * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $eval: function(expr, locals) { - return $parse(expr)(this, locals); - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$evalAsync - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Executes the expression on the current scope at a later point in time. - * - * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that: - * - * - it will execute in the current script execution context (before any DOM rendering). - * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after - * `expression` execution. - * - * Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - */ - $evalAsync: function(expr) { - this.$$asyncQueue.push(expr); - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$apply - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * `$apply()` is used to execute an expression in angular from outside of the angular framework. - * (For example from browser DOM events, setTimeout, XHR or third party libraries). - * Because we are calling into the angular framework we need to perform proper scope life-cycle - * of {@link ng.$exceptionHandler exception handling}, - * {@link ng.$rootScope.Scope#$digest executing watches}. - * - * ## Life cycle - * - * # Pseudo-Code of `$apply()` - *
-           function $apply(expr) {
-             try {
-               return $eval(expr);
-             } catch (e) {
-               $exceptionHandler(e);
-             } finally {
-               $root.$digest();
-             }
-           }
-       * 
- * - * - * Scope's `$apply()` method transitions through the following stages: - * - * 1. The {@link guide/expression expression} is executed using the - * {@link ng.$rootScope.Scope#$eval $eval()} method. - * 2. Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression - * was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. - * - * - * @param {(string|function())=} exp An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $apply: function(expr) { - try { - beginPhase('$apply'); - return this.$eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - clearPhase(); - try { - $rootScope.$digest(); - } catch (e) { - $exceptionHandler(e); - throw e; - } - } - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$on - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of - * event life cycle. - * - * The event listener function format is: `function(event, args...)`. The `event` object - * passed into the listener has the following attributes: - * - * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed. - * - `currentScope` - `{Scope}`: the current scope which is handling the event. - * - `name` - `{string}`: Name of the event. - * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event - * propagation (available only for events that were `$emit`-ed). - * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true. - * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. - * - * @param {string} name Event name to listen on. - * @param {function(event, args...)} listener Function to call when the event is emitted. - * @returns {function()} Returns a deregistration function for this listener. - */ - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; - } - namedListeners.push(listener); - - return function() { - namedListeners[indexOf(namedListeners, listener)] = null; - }; - }, - - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$emit - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Dispatches an event `name` upwards through the scope hierarchy notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$emit` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified. - * Afterwards, the event traverses upwards toward the root scope and calls all registered - * listeners along the way. The event will stop propagating if one of the listeners cancels it. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to emit. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. - * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} - */ - $emit: function(name, args) { - var empty = [], - namedListeners, - scope = this, - stopPropagation = false, - event = { - name: name, - targetScope: scope, - stopPropagation: function() {stopPropagation = true;}, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }, - listenerArgs = concat([event], arguments, 1), - i, length; - - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i=0, length=namedListeners.length; i 7), - hasEvent: function(event) { - // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have - // it. In particular the event is not fired when backspace or delete key are pressed or - // when cut operation is performed. - if (event == 'input' && msie == 9) return false; - - if (isUndefined(eventSupport[event])) { - var divElm = $window.document.createElement('div'); - eventSupport[event] = 'on' + event in divElm; - } - - return eventSupport[event]; - }, - // TODO(i): currently there is no way to feature detect CSP without triggering alerts - csp: false - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$window - * - * @description - * A reference to the browser's `window` object. While `window` - * is globally available in JavaScript, it causes testability problems, because - * it is a global variable. In angular we always refer to it through the - * `$window` service, so it may be overriden, removed or mocked for testing. - * - * All expressions are evaluated with respect to current scope so they don't - * suffer from window globality. - * - * @example - - - -
- - -
-
- - it('should display the greeting in the input box', function() { - input('greeting').enter('Hello, E2E Tests'); - // If we click the button it will block the test runner - // element(':button').click(); - }); - -
- */ -function $WindowProvider(){ - this.$get = valueFn(window); -} - -/** - * Parse headers into key value object - * - * @param {string} headers Raw headers as a string - * @returns {Object} Parsed headers as key value object - */ -function parseHeaders(headers) { - var parsed = {}, key, val, i; - - if (!headers) return parsed; - - forEach(headers.split('\n'), function(line) { - i = line.indexOf(':'); - key = lowercase(trim(line.substr(0, i))); - val = trim(line.substr(i + 1)); - - if (key) { - if (parsed[key]) { - parsed[key] += ', ' + val; - } else { - parsed[key] = val; - } - } - }); - - return parsed; -} - - -/** - * Returns a function that provides access to parsed headers. - * - * Headers are lazy parsed when first requested. - * @see parseHeaders - * - * @param {(string|Object)} headers Headers to provide access to. - * @returns {function(string=)} Returns a getter function which if called with: - * - * - if called with single an argument returns a single header value or null - * - if called with no arguments returns an object containing all headers. - */ -function headersGetter(headers) { - var headersObj = isObject(headers) ? headers : undefined; - - return function(name) { - if (!headersObj) headersObj = parseHeaders(headers); - - if (name) { - return headersObj[lowercase(name)] || null; - } - - return headersObj; - }; -} - - -/** - * Chain all given functions - * - * This function is used for both request and response transforming - * - * @param {*} data Data to transform. - * @param {function(string=)} headers Http headers getter fn. - * @param {(function|Array.)} fns Function or an array of functions. - * @returns {*} Transformed data. - */ -function transformData(data, headers, fns) { - if (isFunction(fns)) - return fns(data, headers); - - forEach(fns, function(fn) { - data = fn(data, headers); - }); - - return data; -} - - -function isSuccess(status) { - return 200 <= status && status < 300; -} - - -function $HttpProvider() { - var JSON_START = /^\s*(\[|\{[^\{])/, - JSON_END = /[\}\]]\s*$/, - PROTECTION_PREFIX = /^\)\]\}',?\n/; - - var $config = this.defaults = { - // transform incoming response data - transformResponse: [function(data) { - if (isString(data)) { - // strip json vulnerability protection prefix - data = data.replace(PROTECTION_PREFIX, ''); - if (JSON_START.test(data) && JSON_END.test(data)) - data = fromJson(data, true); - } - return data; - }], - - // transform outgoing request data - transformRequest: [function(d) { - return isObject(d) && !isFile(d) ? toJson(d) : d; - }], - - // default headers - headers: { - common: { - 'Accept': 'application/json, text/plain, */*', - 'X-Requested-With': 'XMLHttpRequest' - }, - post: {'Content-Type': 'application/json;charset=utf-8'}, - put: {'Content-Type': 'application/json;charset=utf-8'} - } - }; - - var providerResponseInterceptors = this.responseInterceptors = []; - - this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', - function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { - - var defaultCache = $cacheFactory('$http'), - responseInterceptors = []; - - forEach(providerResponseInterceptors, function(interceptor) { - responseInterceptors.push( - isString(interceptor) - ? $injector.get(interceptor) - : $injector.invoke(interceptor) - ); - }); - - - /** - * @ngdoc function - * @name ng.$http - * @requires $httpBackend - * @requires $browser - * @requires $cacheFactory - * @requires $rootScope - * @requires $q - * @requires $injector - * - * @description - * The `$http` service is a core Angular service that facilitates communication with the remote - * HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest - * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}. - * - * For unit testing applications that use `$http` service, see - * {@link ngMock.$httpBackend $httpBackend mock}. - * - * For a higher level of abstraction, please check out the {@link ngResource.$resource - * $resource} service. - * - * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by - * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage - * it is important to familiarize yourself with these APIs and the guarantees they provide. - * - * - * # General usage - * The `$http` service is a function which takes a single argument — a configuration object — - * that is used to generate an HTTP request and returns a {@link ng.$q promise} - * with two $http specific methods: `success` and `error`. - * - *
-     *   $http({method: 'GET', url: '/someUrl'}).
-     *     success(function(data, status, headers, config) {
-     *       // this callback will be called asynchronously
-     *       // when the response is available
-     *     }).
-     *     error(function(data, status, headers, config) {
-     *       // called asynchronously if an error occurs
-     *       // or server returns response with an error status.
-     *     });
-     * 
- * - * Since the returned value of calling the $http function is a `promise`, you can also use - * the `then` method to register callbacks, and these callbacks will receive a single argument – - * an object representing the response. See the API signature and type info below for more - * details. - * - * A response status code between 200 and 299 is considered a success status and - * will result in the success callback being called. Note that if the response is a redirect, - * XMLHttpRequest will transparently follow it, meaning that the error callback will not be - * called for such responses. - * - * # Shortcut methods - * - * Since all invocations of the $http service require passing in an HTTP method and URL, and - * POST/PUT requests require request data to be provided as well, shortcut methods - * were created: - * - *
-     *   $http.get('/someUrl').success(successCallback);
-     *   $http.post('/someUrl', data).success(successCallback);
-     * 
- * - * Complete list of shortcut methods: - * - * - {@link ng.$http#get $http.get} - * - {@link ng.$http#head $http.head} - * - {@link ng.$http#post $http.post} - * - {@link ng.$http#put $http.put} - * - {@link ng.$http#delete $http.delete} - * - {@link ng.$http#jsonp $http.jsonp} - * - * - * # Setting HTTP Headers - * - * The $http service will automatically add certain HTTP headers to all requests. These defaults - * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration - * object, which currently contains this default configuration: - * - * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): - * - `Accept: application/json, text/plain, * / *` - * - `X-Requested-With: XMLHttpRequest` - * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) - * - `Content-Type: application/json` - * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) - * - `Content-Type: application/json` - * - * To add or overwrite these defaults, simply add or remove a property from these configuration - * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object - * with the lowercased HTTP method name as the key, e.g. - * `$httpProvider.defaults.headers.get['My-Header']='value'`. - * - * Additionally, the defaults can be set at runtime via the `$http.defaults` object in the same - * fashion. - * - * - * # Transforming Requests and Responses - * - * Both requests and responses can be transformed using transform functions. By default, Angular - * applies these transformations: - * - * Request transformations: - * - * - If the `data` property of the request configuration object contains an object, serialize it into - * JSON format. - * - * Response transformations: - * - * - If XSRF prefix is detected, strip it (see Security Considerations section below). - * - If JSON response is detected, deserialize it using a JSON parser. - * - * To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and - * `$httpProvider.defaults.transformResponse` properties. These properties are by default an - * array of transform functions, which allows you to `push` or `unshift` a new transformation function into the - * transformation chain. You can also decide to completely override any default transformations by assigning your - * transformation functions to these properties directly without the array wrapper. - * - * Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or - * `transformResponse` properties of the configuration object passed into `$http`. - * - * - * # Caching - * - * To enable caching, set the configuration property `cache` to `true`. When the cache is - * enabled, `$http` stores the response from the server in local cache. Next time the - * response is served from the cache without sending a request to the server. - * - * Note that even if the response is served from cache, delivery of the data is asynchronous in - * the same way that real requests are. - * - * If there are multiple GET requests for the same URL that should be cached using the same - * cache, but the cache is not populated yet, only one request to the server will be made and - * the remaining requests will be fulfilled using the response from the first request. - * - * - * # Response interceptors - * - * Before you start creating interceptors, be sure to understand the - * {@link ng.$q $q and deferred/promise APIs}. - * - * For purposes of global error handling, authentication or any kind of synchronous or - * asynchronous preprocessing of received responses, it is desirable to be able to intercept - * responses for http requests before they are handed over to the application code that - * initiated these requests. The response interceptors leverage the {@link ng.$q - * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing. - * - * The interceptors are service factories that are registered with the $httpProvider by - * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and - * injected with dependencies (if specified) and returns the interceptor — a function that - * takes a {@link ng.$q promise} and returns the original or a new promise. - * - *
-     *   // register the interceptor as a service
-     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
-     *     return function(promise) {
-     *       return promise.then(function(response) {
-     *         // do something on success
-     *       }, function(response) {
-     *         // do something on error
-     *         if (canRecover(response)) {
-     *           return responseOrNewPromise
-     *         }
-     *         return $q.reject(response);
-     *       });
-     *     }
-     *   });
-     *
-     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');
-     *
-     *
-     *   // register the interceptor via an anonymous factory
-     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
-     *     return function(promise) {
-     *       // same as above
-     *     }
-     *   });
-     * 
- * - * - * # Security Considerations - * - * When designing web applications, consider security threats from: - * - * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx - * JSON vulnerability} - * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} - * - * Both server and the client must cooperate in order to eliminate these threats. Angular comes - * pre-configured with strategies that address these issues, but for this to work backend server - * cooperation is required. - * - * ## JSON Vulnerability Protection - * - * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx - * JSON vulnerability} allows third party website to turn your JSON resource URL into - * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To - * counter this your server can prefix all JSON requests with following string `")]}',\n"`. - * Angular will automatically strip the prefix before processing it as JSON. - * - * For example if your server needs to return: - *
-     * ['one','two']
-     * 
- * - * which is vulnerable to attack, your server can return: - *
-     * )]}',
-     * ['one','two']
-     * 
- * - * Angular will strip the prefix, before processing the JSON. - * - * - * ## Cross Site Request Forgery (XSRF) Protection - * - * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which - * an unauthorized site can gain your user's private data. Angular provides a mechanism - * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie - * called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that - * runs on your domain could read the cookie, your server can be assured that the XHR came from - * JavaScript running on your domain. - * - * To take advantage of this, your server needs to set a token in a JavaScript readable session - * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the - * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure - * that only JavaScript running on your domain could have sent the request. The token must be - * unique for each user and must be verifiable by the server (to prevent the JavaScript from making - * up its own tokens). We recommend that the token is a digest of your site's authentication - * cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security. - * - * - * @param {object} config Object describing the request to be made and how it should be - * processed. The object has following properties: - * - * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) - * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. - * - **params** – `{Object.}` – Map of strings or objects which will be turned to - * `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified. - * - **data** – `{string|Object}` – Data to be sent as the request message data. - * - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server. - * - **transformRequest** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * - **transformResponse** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * response body and headers and returns its transformed (typically deserialized) version. - * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. - * - **timeout** – `{number}` – timeout in milliseconds. - * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the - * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 - * requests with credentials} for more information. - * - * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the - * standard `then` method and two http specific methods: `success` and `error`. The `then` - * method takes two arguments a success and an error callback which will be called with a - * response object. The `success` and `error` methods take a single argument - a function that - * will be called when the request succeeds or fails respectively. The arguments passed into - * these functions are destructured representation of the response object passed into the - * `then` method. The response object has these properties: - * - * - **data** – `{string|Object}` – The response body transformed with the transform functions. - * - **status** – `{number}` – HTTP status code of the response. - * - **headers** – `{function([headerName])}` – Header getter function. - * - **config** – `{Object}` – The configuration object that was used to generate the request. - * - * @property {Array.} pendingRequests Array of config objects for currently pending - * requests. This is primarily meant to be used for debugging purposes. - * - * - * @example - - -
- - -
- - - -
http status code: {{status}}
-
http response data: {{data}}
-
-
- - function FetchCtrl($scope, $http, $templateCache) { - $scope.method = 'GET'; - $scope.url = 'http-hello.html'; - - $scope.fetch = function() { - $scope.code = null; - $scope.response = null; - - $http({method: $scope.method, url: $scope.url, cache: $templateCache}). - success(function(data, status) { - $scope.status = status; - $scope.data = data; - }). - error(function(data, status) { - $scope.data = data || "Request failed"; - $scope.status = status; - }); - }; - - $scope.updateModel = function(method, url) { - $scope.method = method; - $scope.url = url; - }; - } - - - Hello, $http! - - - it('should make an xhr GET request', function() { - element(':button:contains("Sample GET")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Hello, \$http!/); - }); - - it('should make a JSONP request to angularjs.org', function() { - element(':button:contains("Sample JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Super Hero!/); - }); - - it('should make JSONP request to invalid URL and invoke the error handler', - function() { - element(':button:contains("Invalid JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('0'); - expect(binding('data')).toBe('Request failed'); - }); - -
- */ - function $http(config) { - config.method = uppercase(config.method); - - var reqTransformFn = config.transformRequest || $config.transformRequest, - respTransformFn = config.transformResponse || $config.transformResponse, - defHeaders = $config.headers, - reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']}, - defHeaders.common, defHeaders[lowercase(config.method)], config.headers), - reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn), - promise; - - // strip content-type if data is undefined - if (isUndefined(config.data)) { - delete reqHeaders['Content-Type']; - } - - // send request - promise = sendReq(config, reqData, reqHeaders); - - - // transform future response - promise = promise.then(transformResponse, transformResponse); - - // apply interceptors - forEach(responseInterceptors, function(interceptor) { - promise = interceptor(promise); - }); - - promise.success = function(fn) { - promise.then(function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - - promise.error = function(fn) { - promise.then(null, function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - - return promise; - - function transformResponse(response) { - // make a copy since the response must be cacheable - var resp = extend({}, response, { - data: transformData(response.data, response.headers, respTransformFn) - }); - return (isSuccess(response.status)) - ? resp - : $q.reject(resp); - } - } - - $http.pendingRequests = []; - - /** - * @ngdoc method - * @name ng.$http#get - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `GET` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#delete - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `DELETE` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#head - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `HEAD` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#jsonp - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `JSONP` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request. - * Should contain `JSON_CALLBACK` string. - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethods('get', 'delete', 'head', 'jsonp'); - - /** - * @ngdoc method - * @name ng.$http#post - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `POST` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#put - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `PUT` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethodsWithData('post', 'put'); - - /** - * @ngdoc property - * @name ng.$http#defaults - * @propertyOf ng.$http - * - * @description - * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of - * default headers as well as request and response transformations. - * - * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. - */ - $http.defaults = $config; - - - return $http; - - - function createShortMethods(names) { - forEach(arguments, function(name) { - $http[name] = function(url, config) { - return $http(extend(config || {}, { - method: name, - url: url - })); - }; - }); - } - - - function createShortMethodsWithData(name) { - forEach(arguments, function(name) { - $http[name] = function(url, data, config) { - return $http(extend(config || {}, { - method: name, - url: url, - data: data - })); - }; - }); - } - - - /** - * Makes the request. - * - * !!! ACCESSES CLOSURE VARS: - * $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests - */ - function sendReq(config, reqData, reqHeaders) { - var deferred = $q.defer(), - promise = deferred.promise, - cache, - cachedResp, - url = buildUrl(config.url, config.params); - - $http.pendingRequests.push(config); - promise.then(removePendingReq, removePendingReq); - - - if (config.cache && config.method == 'GET') { - cache = isObject(config.cache) ? config.cache : defaultCache; - } - - if (cache) { - cachedResp = cache.get(url); - if (cachedResp) { - if (cachedResp.then) { - // cached request has already been sent, but there is no response yet - cachedResp.then(removePendingReq, removePendingReq); - return cachedResp; - } else { - // serving from cache - if (isArray(cachedResp)) { - resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2])); - } else { - resolvePromise(cachedResp, 200, {}); - } - } - } else { - // put the promise for the non-transformed response into cache as a placeholder - cache.put(url, promise); - } - } - - // if we won't have the response in cache, send the request to the backend - if (!cachedResp) { - $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, - config.withCredentials); - } - - return promise; - - - /** - * Callback registered to $httpBackend(): - * - caches the response if desired - * - resolves the raw $http promise - * - calls $apply - */ - function done(status, response, headersString) { - if (cache) { - if (isSuccess(status)) { - cache.put(url, [status, response, parseHeaders(headersString)]); - } else { - // remove promise from the cache - cache.remove(url); - } - } - - resolvePromise(response, status, headersString); - $rootScope.$apply(); - } - - - /** - * Resolves the raw $http promise. - */ - function resolvePromise(response, status, headers) { - // normalize internal statuses to 0 - status = Math.max(status, 0); - - (isSuccess(status) ? deferred.resolve : deferred.reject)({ - data: response, - status: status, - headers: headersGetter(headers), - config: config - }); - } - - - function removePendingReq() { - var idx = indexOf($http.pendingRequests, config); - if (idx !== -1) $http.pendingRequests.splice(idx, 1); - } - } - - - function buildUrl(url, params) { - if (!params) return url; - var parts = []; - forEachSorted(params, function(value, key) { - if (value == null || value == undefined) return; - if (isObject(value)) { - value = toJson(value); - } - parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - }); - return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); - } - - - }]; -} - -var XHR = window.XMLHttpRequest || function() { - try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} - try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} - try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} - throw new Error("This browser does not support XMLHttpRequest."); -}; - - -/** - * @ngdoc object - * @name ng.$httpBackend - * @requires $browser - * @requires $window - * @requires $document - * - * @description - * HTTP backend used by the {@link ng.$http service} that delegates to - * XMLHttpRequest object or JSONP and deals with browser incompatibilities. - * - * You should never need to use this service directly, instead use the higher-level abstractions: - * {@link ng.$http $http} or {@link ngResource.$resource $resource}. - * - * During testing this implementation is swapped with {@link ngMock.$httpBackend mock - * $httpBackend} which can be trained with responses. - */ -function $HttpBackendProvider() { - this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { - return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks, - $document[0], $window.location.protocol.replace(':', '')); - }]; -} - -function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) { - // TODO(vojta): fix the signature - return function(method, url, post, callback, headers, timeout, withCredentials) { - $browser.$$incOutstandingRequestCount(); - url = url || $browser.url(); - - if (lowercase(method) == 'jsonp') { - var callbackId = '_' + (callbacks.counter++).toString(36); - callbacks[callbackId] = function(data) { - callbacks[callbackId].data = data; - }; - - jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), - function() { - if (callbacks[callbackId].data) { - completeRequest(callback, 200, callbacks[callbackId].data); - } else { - completeRequest(callback, -2); - } - delete callbacks[callbackId]; - }); - } else { - var xhr = new XHR(); - xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (value) xhr.setRequestHeader(key, value); - }); - - var status; - - // In IE6 and 7, this might be called synchronously when xhr.send below is called and the - // response is in the cache. the promise api will ensure that to the app code the api is - // always async - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - var responseHeaders = xhr.getAllResponseHeaders(); - - // TODO(vojta): remove once Firefox 21 gets released. - // begin: workaround to overcome Firefox CORS http response headers bug - // https://bugzilla.mozilla.org/show_bug.cgi?id=608735 - // Firefox already patched in nightly. Should land in Firefox 21. - - // CORS "simple response headers" http://www.w3.org/TR/cors/ - var value, - simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type", - "Expires", "Last-Modified", "Pragma"]; - if (!responseHeaders) { - responseHeaders = ""; - forEach(simpleHeaders, function (header) { - var value = xhr.getResponseHeader(header); - if (value) { - responseHeaders += header + ": " + value + "\n"; - } - }); - } - // end of the workaround. - - completeRequest(callback, status || xhr.status, xhr.responseText, - responseHeaders); - } - }; - - if (withCredentials) { - xhr.withCredentials = true; - } - - xhr.send(post || ''); - - if (timeout > 0) { - $browserDefer(function() { - status = -1; - xhr.abort(); - }, timeout); - } - } - - - function completeRequest(callback, status, response, headersString) { - // URL_MATCH is defined in src/service/location.js - var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1]; - - // fix status code for file protocol (it's always 0) - status = (protocol == 'file') ? (response ? 200 : 404) : status; - - // normalize IE bug (http://bugs.jquery.com/ticket/1450) - status = status == 1223 ? 204 : status; - - callback(status, response, headersString); - $browser.$$completeOutstandingRequest(noop); - } - }; - - function jsonpReq(url, done) { - // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: - // - fetches local scripts via XHR and evals them - // - adds and immediately removes script elements from the document - var script = rawDocument.createElement('script'), - doneWrapper = function() { - rawDocument.body.removeChild(script); - if (done) done(); - }; - - script.type = 'text/javascript'; - script.src = url; - - if (msie) { - script.onreadystatechange = function() { - if (/loaded|complete/.test(script.readyState)) doneWrapper(); - }; - } else { - script.onload = script.onerror = doneWrapper; - } - - rawDocument.body.appendChild(script); - } -} - -/** - * @ngdoc object - * @name ng.$locale - * - * @description - * $locale service provides localization rules for various Angular components. As of right now the - * only public api is: - * - * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) - */ -function $LocaleProvider(){ - this.$get = function() { - return { - id: 'en-us', - - NUMBER_FORMATS: { - DECIMAL_SEP: '.', - GROUP_SEP: ',', - PATTERNS: [ - { // Decimal Pattern - minInt: 1, - minFrac: 0, - maxFrac: 3, - posPre: '', - posSuf: '', - negPre: '-', - negSuf: '', - gSize: 3, - lgSize: 3 - },{ //Currency Pattern - minInt: 1, - minFrac: 2, - maxFrac: 2, - posPre: '\u00A4', - posSuf: '', - negPre: '(\u00A4', - negSuf: ')', - gSize: 3, - lgSize: 3 - } - ], - CURRENCY_SYM: '$' - }, - - DATETIME_FORMATS: { - MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December' - .split(','), - SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), - DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), - SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), - AMPMS: ['AM','PM'], - medium: 'MMM d, y h:mm:ss a', - short: 'M/d/yy h:mm a', - fullDate: 'EEEE, MMMM d, y', - longDate: 'MMMM d, y', - mediumDate: 'MMM d, y', - shortDate: 'M/d/yy', - mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' - }, - - pluralCat: function(num) { - if (num === 1) { - return 'one'; - } - return 'other'; - } - }; - }; -} - -function $TimeoutProvider() { - this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler', - function($rootScope, $browser, $q, $exceptionHandler) { - var deferreds = {}; - - - /** - * @ngdoc function - * @name ng.$timeout - * @requires $browser - * - * @description - * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch - * block and delegates any exceptions to - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * The return value of registering a timeout function is a promise, which will be resolved when - * the timeout is reached and the timeout function is executed. - * - * To cancel a timeout request, call `$timeout.cancel(promise)`. - * - * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to - * synchronously flush the queue of deferred functions. - * - * @param {function()} fn A function, whose execution should be delayed. - * @param {number=} [delay=0] Delay in milliseconds. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this - * promise will be resolved with is the return value of the `fn` function. - */ - function timeout(fn, delay, invokeApply) { - var deferred = $q.defer(), - promise = deferred.promise, - skipApply = (isDefined(invokeApply) && !invokeApply), - timeoutId, cleanup; - - timeoutId = $browser.defer(function() { - try { - deferred.resolve(fn()); - } catch(e) { - deferred.reject(e); - $exceptionHandler(e); - } - - if (!skipApply) $rootScope.$apply(); - }, delay); - - cleanup = function() { - delete deferreds[promise.$$timeoutId]; - }; - - promise.$$timeoutId = timeoutId; - deferreds[timeoutId] = deferred; - promise.then(cleanup, cleanup); - - return promise; - } - - - /** - * @ngdoc function - * @name ng.$timeout#cancel - * @methodOf ng.$timeout - * - * @description - * Cancels a task associated with the `promise`. As a result of this, the promise will be - * resolved with a rejection. - * - * @param {Promise=} promise Promise returned by the `$timeout` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully - * canceled. - */ - timeout.cancel = function(promise) { - if (promise && promise.$$timeoutId in deferreds) { - deferreds[promise.$$timeoutId].reject('canceled'); - return $browser.defer.cancel(promise.$$timeoutId); - } - return false; - }; - - return timeout; - }]; -} - -/** - * @ngdoc object - * @name ng.$filterProvider - * @description - * - * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To - * achieve this a filter definition consists of a factory function which is annotated with dependencies and is - * responsible for creating a filter function. - * - *
- *   // Filter registration
- *   function MyModule($provide, $filterProvider) {
- *     // create a service to demonstrate injection (not always needed)
- *     $provide.value('greet', function(name){
- *       return 'Hello ' + name + '!';
- *     });
- *
- *     // register a filter factory which uses the
- *     // greet service to demonstrate DI.
- *     $filterProvider.register('greet', function(greet){
- *       // return the filter function which uses the greet service
- *       // to generate salutation
- *       return function(text) {
- *         // filters need to be forgiving so check input validity
- *         return text && greet(text) || text;
- *       };
- *     });
- *   }
- * 
- * - * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`. - *
- *   it('should be the same instance', inject(
- *     function($filterProvider) {
- *       $filterProvider.register('reverse', function(){
- *         return ...;
- *       });
- *     },
- *     function($filter, reverseFilter) {
- *       expect($filter('reverse')).toBe(reverseFilter);
- *     });
- * 
- * - * - * For more information about how angular filters work, and how to create your own filters, see - * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer - * Guide. - */ -/** - * @ngdoc method - * @name ng.$filterProvider#register - * @methodOf ng.$filterProvider - * @description - * Register filter factory function. - * - * @param {String} name Name of the filter. - * @param {function} fn The filter factory function which is injectable. - */ - - -/** - * @ngdoc function - * @name ng.$filter - * @function - * @description - * Filters are used for formatting data displayed to the user. - * - * The general syntax in templates is as follows: - * - * {{ expression [| filter_name[:parameter_value] ... ] }} - * - * @param {String} name Name of the filter function to retrieve - * @return {Function} the filter function - */ -$FilterProvider.$inject = ['$provide']; -function $FilterProvider($provide) { - var suffix = 'Filter'; - - function register(name, factory) { - return $provide.factory(name + suffix, factory); - } - this.register = register; - - this.$get = ['$injector', function($injector) { - return function(name) { - return $injector.get(name + suffix); - } - }]; - - //////////////////////////////////////// - - register('currency', currencyFilter); - register('date', dateFilter); - register('filter', filterFilter); - register('json', jsonFilter); - register('limitTo', limitToFilter); - register('lowercase', lowercaseFilter); - register('number', numberFilter); - register('orderBy', orderByFilter); - register('uppercase', uppercaseFilter); -} - -/** - * @ngdoc filter - * @name ng.filter:filter - * @function - * - * @description - * Selects a subset of items from `array` and returns it as a new array. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {Array} array The source array. - * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. - * - * Can be one of: - * - * - `string`: Predicate that results in a substring match using the value of `expression` - * string. All strings or objects with string properties in `array` that contain this string - * will be returned. The predicate can be negated by prefixing the string with `!`. - * - * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items - * which have property `name` containing "M" and property `phone` containing "1". A special - * property name `$` can be used (as in `{$:"text"}`) to accept a match against any - * property of the object. That's equivalent to the simple substring match with a `string` - * as described above. - * - * - `function`: A predicate function can be used to write arbitrary filters. The function is - * called for each element of `array`. The final result is an array of those elements that - * the predicate returned true for. - * - * @example - - -
- - Search: - - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- Any:
- Name only
- Phone only
- - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Adam']); - - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['John', 'Julie']); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Julie']); - }); - -
- */ -function filterFilter() { - return function(array, expression) { - if (!isArray(array)) return array; - var predicates = []; - predicates.check = function(value) { - for (var j = 0; j < predicates.length; j++) { - if(!predicates[j](value)) { - return false; - } - } - return true; - }; - var search = function(obj, text){ - if (text.charAt(0) === '!') { - return !search(obj, text.substr(1)); - } - switch (typeof obj) { - case "boolean": - case "number": - case "string": - return ('' + obj).toLowerCase().indexOf(text) > -1; - case "object": - for ( var objKey in obj) { - if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { - return true; - } - } - return false; - case "array": - for ( var i = 0; i < obj.length; i++) { - if (search(obj[i], text)) { - return true; - } - } - return false; - default: - return false; - } - }; - switch (typeof expression) { - case "boolean": - case "number": - case "string": - expression = {$:expression}; - case "object": - for (var key in expression) { - if (key == '$') { - (function() { - var text = (''+expression[key]).toLowerCase(); - if (!text) return; - predicates.push(function(value) { - return search(value, text); - }); - })(); - } else { - (function() { - var path = key; - var text = (''+expression[key]).toLowerCase(); - if (!text) return; - predicates.push(function(value) { - return search(getter(value, path), text); - }); - })(); - } - } - break; - case 'function': - predicates.push(expression); - break; - default: - return array; - } - var filtered = []; - for ( var j = 0; j < array.length; j++) { - var value = array[j]; - if (predicates.check(value)) { - filtered.push(value); - } - } - return filtered; - } -} - -/** - * @ngdoc filter - * @name ng.filter:currency - * @function - * - * @description - * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default - * symbol for current locale is used. - * - * @param {number} amount Input to filter. - * @param {string=} symbol Currency symbol or identifier to be displayed. - * @returns {string} Formatted number. - * - * - * @example - - - -
-
- default currency symbol ($): {{amount | currency}}
- custom currency identifier (USD$): {{amount | currency:"USD$"}} -
-
- - it('should init with 1234.56', function() { - expect(binding('amount | currency')).toBe('$1,234.56'); - expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56'); - }); - it('should update', function() { - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('($1,234.00)'); - expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); - }); - -
- */ -currencyFilter.$inject = ['$locale']; -function currencyFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(amount, currencySymbol){ - if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; - return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). - replace(/\u00A4/g, currencySymbol); - }; -} - -/** - * @ngdoc filter - * @name ng.filter:number - * @function - * - * @description - * Formats a number as text. - * - * If the input is not a number an empty string is returned. - * - * @param {number|string} number Number to format. - * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to. - * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. - * - * @example - - - -
- Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}} -
-
- - it('should format numbers', function() { - expect(binding('val | number')).toBe('1,234.568'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); - }); - - it('should update', function() { - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.333'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); - -
- */ - - -numberFilter.$inject = ['$locale']; -function numberFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(number, fractionSize) { - return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, - fractionSize); - }; -} - -var DECIMAL_SEP = '.'; -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (isNaN(number) || !isFinite(number)) return ''; - - var isNegative = number < 0; - number = Math.abs(number); - var numStr = number + '', - formatedText = '', - parts = []; - - var hasExponent = false; - if (numStr.indexOf('e') !== -1) { - var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); - if (match && match[2] == '-' && match[3] > fractionSize + 1) { - numStr = '0'; - } else { - formatedText = numStr; - hasExponent = true; - } - } - - if (!hasExponent) { - var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; - - // determine fractionSize if it is not specified - if (isUndefined(fractionSize)) { - fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); - } - - var pow = Math.pow(10, fractionSize); - number = Math.round(number * pow) / pow; - var fraction = ('' + number).split(DECIMAL_SEP); - var whole = fraction[0]; - fraction = fraction[1] || ''; - - var pos = 0, - lgroup = pattern.lgSize, - group = pattern.gSize; - - if (whole.length >= (lgroup + group)) { - pos = whole.length - lgroup; - for (var i = 0; i < pos; i++) { - if ((pos - i)%group === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } - } - - for (i = pos; i < whole.length; i++) { - if ((whole.length - i)%lgroup === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } - - // format fraction part. - while(fraction.length < fractionSize) { - fraction += '0'; - } - - if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); - } - - parts.push(isNegative ? pattern.negPre : pattern.posPre); - parts.push(formatedText); - parts.push(isNegative ? pattern.negSuf : pattern.posSuf); - return parts.join(''); -} - -function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while(num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; -} - - -function dateGetter(name, size, offset, trim) { - offset = offset || 0; - return function(date) { - var value = date['get' + name](); - if (offset > 0 || value > -offset) - value += offset; - if (value === 0 && offset == -12 ) value = 12; - return padNumber(value, size, trim); - }; -} - -function dateStrGetter(name, shortForm) { - return function(date, formats) { - var value = date['get' + name](); - var get = uppercase(shortForm ? ('SHORT' + name) : name); - - return formats[get][value]; - }; -} - -function timeZoneGetter(date) { - var zone = -1 * date.getTimezoneOffset(); - var paddedZone = (zone >= 0) ? "+" : ""; - - paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + - padNumber(Math.abs(zone % 60), 2); - - return paddedZone; -} - -function ampmGetter(date, formats) { - return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; -} - -var DATE_FORMATS = { - yyyy: dateGetter('FullYear', 4), - yy: dateGetter('FullYear', 2, 0, true), - y: dateGetter('FullYear', 1), - MMMM: dateStrGetter('Month'), - MMM: dateStrGetter('Month', true), - MM: dateGetter('Month', 2, 1), - M: dateGetter('Month', 1, 1), - dd: dateGetter('Date', 2), - d: dateGetter('Date', 1), - HH: dateGetter('Hours', 2), - H: dateGetter('Hours', 1), - hh: dateGetter('Hours', 2, -12), - h: dateGetter('Hours', 1, -12), - mm: dateGetter('Minutes', 2), - m: dateGetter('Minutes', 1), - ss: dateGetter('Seconds', 2), - s: dateGetter('Seconds', 1), - EEEE: dateStrGetter('Day'), - EEE: dateStrGetter('Day', true), - a: ampmGetter, - Z: timeZoneGetter -}; - -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, - NUMBER_STRING = /^\d+$/; - -/** - * @ngdoc filter - * @name ng.filter:date - * @function - * - * @description - * Formats `date` to a string based on the requested `format`. - * - * `format` string can be composed of the following elements: - * - * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) - * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) - * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) - * * `'MMMM'`: Month in year (January-December) - * * `'MMM'`: Month in year (Jan-Dec) - * * `'MM'`: Month in year, padded (01-12) - * * `'M'`: Month in year (1-12) - * * `'dd'`: Day in month, padded (01-31) - * * `'d'`: Day in month (1-31) - * * `'EEEE'`: Day in Week,(Sunday-Saturday) - * * `'EEE'`: Day in Week, (Sun-Sat) - * * `'HH'`: Hour in day, padded (00-23) - * * `'H'`: Hour in day (0-23) - * * `'hh'`: Hour in am/pm, padded (01-12) - * * `'h'`: Hour in am/pm, (1-12) - * * `'mm'`: Minute in hour, padded (00-59) - * * `'m'`: Minute in hour (0-59) - * * `'ss'`: Second in minute, padded (00-59) - * * `'s'`: Second in minute (0-59) - * * `'a'`: am/pm marker - * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) - * - * `format` string can also be one of the following predefined - * {@link guide/i18n localizable formats}: - * - * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale - * (e.g. Sep 3, 2010 12:05:08 pm) - * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm) - * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale - * (e.g. Friday, September 3, 2010) - * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010 - * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) - * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) - * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm) - * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm) - * - * `format` string can contain literal values. These need to be quoted with single quotes (e.g. - * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence - * (e.g. `"h o''clock"`). - * - * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or - * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its - * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is - * specified in the string input, the time is considered to be in the local timezone. - * @param {string=} format Formatting rules (see Description). If not specified, - * `mediumDate` is used. - * @returns {string} Formatted string or the input if input is not recognized as date/millis. - * - * @example - - - {{1288323623006 | date:'medium'}}: - {{1288323623006 | date:'medium'}}
- {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
- {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
-
- - it('should format date', function() { - expect(binding("1288323623006 | date:'medium'")). - toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). - toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); - }); - -
- */ -dateFilter.$inject = ['$locale']; -function dateFilter($locale) { - - - var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; - function jsonStringToDate(string){ - var match; - if (match = string.match(R_ISO8601_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0; - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); - } - date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); - date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0)); - return date; - } - return string; - } - - - return function(date, format) { - var text = '', - parts = [], - fn, match; - - format = format || 'mediumDate'; - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - if (NUMBER_STRING.test(date)) { - date = int(date); - } else { - date = jsonStringToDate(date); - } - } - - if (isNumber(date)) { - date = new Date(date); - } - - if (!isDate(date)) { - return date; - } - - while(format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; - } - } - - forEach(parts, function(value){ - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS) - : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); - }); - - return text; - }; -} - - -/** - * @ngdoc filter - * @name ng.filter:json - * @function - * - * @description - * Allows you to convert a JavaScript object into JSON string. - * - * This filter is mostly useful for debugging. When using the double curly {{value}} notation - * the binding is automatically converted to JSON. - * - * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. - * @returns {string} JSON string. - * - * - * @example: - - -
{{ {'name':'value'} | json }}
-
- - it('should jsonify filtered objects', function() { - expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/); - }); - -
- * - */ -function jsonFilter() { - return function(object) { - return toJson(object, true); - }; -} - - -/** - * @ngdoc filter - * @name ng.filter:lowercase - * @function - * @description - * Converts string to lowercase. - * @see angular.lowercase - */ -var lowercaseFilter = valueFn(lowercase); - - -/** - * @ngdoc filter - * @name ng.filter:uppercase - * @function - * @description - * Converts string to uppercase. - * @see angular.uppercase - */ -var uppercaseFilter = valueFn(uppercase); - -/** - * @ngdoc function - * @name ng.filter:limitTo - * @function - * - * @description - * Creates a new array containing only a specified number of elements in an array. The elements - * are taken from either the beginning or the end of the source array, as specified by the - * value and sign (positive or negative) of `limit`. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {Array} array Source array to be limited. - * @param {string|Number} limit The length of the returned array. If the `limit` number is - * positive, `limit` number of items from the beginning of the source array are copied. - * If the number is negative, `limit` number of items from the end of the source array are - * copied. The `limit` will be trimmed if it exceeds `array.length` - * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit` - * elements. - * - * @example - - - -
- Limit {{numbers}} to: -

Output: {{ numbers | limitTo:limit }}

-
-
- - it('should limit the numer array to first three items', function() { - expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3'); - expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]'); - }); - - it('should update the output when -3 is entered', function() { - input('limit').enter(-3); - expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]'); - }); - - it('should not exceed the maximum size of input array', function() { - input('limit').enter(100); - expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]'); - }); - -
- */ -function limitToFilter(){ - return function(array, limit) { - if (!(array instanceof Array)) return array; - limit = int(limit); - var out = [], - i, n; - - // check that array is iterable - if (!array || !(array instanceof Array)) - return out; - - // if abs(limit) exceeds maximum length, trim it - if (limit > array.length) - limit = array.length; - else if (limit < -array.length) - limit = -array.length; - - if (limit > 0) { - i = 0; - n = limit; - } else { - i = array.length + limit; - n = array.length; - } - - for (; i} expression A predicate to be - * used by the comparator to determine the order of elements. - * - * Can be one of: - * - * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. - * - `string`: An Angular expression which evaluates to an object to order by, such as 'name' - * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control - * ascending or descending sort order (for example, +name or -name). - * - `Array`: An array of function or string predicates. The first predicate in the array - * is used for sorting, but when two items are equivalent, the next predicate is used. - * - * @param {boolean=} reverse Reverse the order the array. - * @returns {Array} Sorted copy of the source array. - * - * @example - - - -
-
Sorting predicate = {{predicate}}; reverse = {{reverse}}
-
- [ unsorted ] - - - - - - - - - - - -
Name - (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
-
-
- - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('-age'); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example-live a:contains("Name")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example-live a:contains("Phone")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); - -
- */ -orderByFilter.$inject = ['$parse']; -function orderByFilter($parse){ - return function(array, sortPredicate, reverseOrder) { - if (!isArray(array)) return array; - if (!sortPredicate) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate]; - sortPredicate = map(sortPredicate, function(predicate){ - var descending = false, get = predicate || identity; - if (isString(predicate)) { - if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; - predicate = predicate.substring(1); - } - get = $parse(predicate); - } - return reverseComparator(function(a,b){ - return compare(get(a),get(b)); - }, descending); - }); - var arrayCopy = []; - for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } - return arrayCopy.sort(reverseComparator(comparator, reverseOrder)); - - function comparator(o1, o2){ - for ( var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return toBoolean(descending) - ? function(a,b){return comp(b,a);} - : comp; - } - function compare(v1, v2){ - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 == t2) { - if (t1 == "string") v1 = v1.toLowerCase(); - if (t1 == "string") v2 = v2.toLowerCase(); - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; - } - } - } -} - -function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive - } - } - directive.restrict = directive.restrict || 'AC'; - return valueFn(directive); -} - -/** - * @ngdoc directive - * @name ng.directive:a - * @restrict E - * - * @description - * Modifies the default behavior of html A tag, so that the default action is prevented when href - * attribute is empty. - * - * The reasoning for this change is to allow easy creation of action links with `ngClick` directive - * without changing the location or causing page reloads, e.g.: - * `Save` - */ -var htmlAnchorDirective = valueFn({ - restrict: 'E', - compile: function(element, attr) { - - if (msie <= 8) { - - // turn link into a stylable link in IE - // but only if it doesn't have name attribute, in which case it's an anchor - if (!attr.href && !attr.name) { - attr.$set('href', ''); - } - - // add a comment node to anchors to workaround IE bug that causes element content to be reset - // to new attribute content if attribute is updated with value containing @ and element also - // contains value with @ - // see issue #1949 - element.append(document.createComment('IE fix')); - } - - return function(scope, element) { - element.bind('click', function(event){ - // if we have no href url, then don't navigate anywhere. - if (!element.attr('href')) { - event.preventDefault(); - } - }); - } - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngHref - * @restrict A - * - * @description - * Using Angular markup like {{hash}} in an href attribute makes - * the page open to a wrong URL, if the user clicks that link before - * angular has a chance to replace the {{hash}} with actual URL, the - * link will be broken and will most likely return a 404 error. - * The `ngHref` directive solves this problem. - * - * The buggy way to write it: - *
- * 
- * 
- * - * The correct way to write it: - *
- * 
- * 
- * - * @element A - * @param {template} ngHref any string which can contain `{{}}` markup. - * - * @example - * This example uses `link` variable inside `href` attribute: - - -
-
link 1 (link, don't reload)
- link 2 (link, don't reload)
- link 3 (link, reload!)
- anchor (link, don't reload)
- anchor (no link)
- link (link, change location) - - - it('should execute ng-click but not reload when href without value', function() { - element('#link-1').click(); - expect(input('value').val()).toEqual('1'); - expect(element('#link-1').attr('href')).toBe(""); - }); - - it('should execute ng-click but not reload when href empty string', function() { - element('#link-2').click(); - expect(input('value').val()).toEqual('2'); - expect(element('#link-2').attr('href')).toBe(""); - }); - - it('should execute ng-click and change url when ng-href specified', function() { - expect(element('#link-3').attr('href')).toBe("/123"); - - element('#link-3').click(); - expect(browser().window().path()).toEqual('/123'); - }); - - it('should execute ng-click but not reload when href empty string and name specified', function() { - element('#link-4').click(); - expect(input('value').val()).toEqual('4'); - expect(element('#link-4').attr('href')).toBe(''); - }); - - it('should execute ng-click but not reload when no href but name specified', function() { - element('#link-5').click(); - expect(input('value').val()).toEqual('5'); - expect(element('#link-5').attr('href')).toBe(undefined); - }); - - it('should only change url when only ng-href', function() { - input('value').enter('6'); - expect(element('#link-6').attr('href')).toBe('6'); - - element('#link-6').click(); - expect(browser().location().url()).toEqual('/6'); - }); - - - */ - -/** - * @ngdoc directive - * @name ng.directive:ngSrc - * @restrict A - * - * @description - * Using Angular markup like `{{hash}}` in a `src` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until Angular replaces the expression inside - * `{{hash}}`. The `ngSrc` directive solves this problem. - * - * The buggy way to write it: - *
- * 
- * 
- * - * The correct way to write it: - *
- * 
- * 
- * - * @element IMG - * @param {template} ngSrc any string which can contain `{{}}` markup. - */ - -/** - * @ngdoc directive - * @name ng.directive:ngDisabled - * @restrict A - * - * @description - * - * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: - *
- * 
- * - *
- *
- * - * The HTML specs do not require browsers to preserve the special attributes such as disabled. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngDisabled` directive. - * - * @example - - - Click me to toggle:
- -
- - it('should toggle button', function() { - expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy(); - }); - -
- * - * @element INPUT - * @param {expression} ngDisabled Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngChecked - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as checked. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngChecked` directive. - * @example - - - Check me to check both:
- -
- - it('should check both checkBoxes', function() { - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy(); - input('master').check(); - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy(); - }); - -
- * - * @element INPUT - * @param {expression} ngChecked Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMultiple - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as multiple. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngMultiple` directive. - * - * @example - - - Check me check multiple:
- -
- - it('should toggle multiple', function() { - expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy(); - }); - -
- * - * @element SELECT - * @param {expression} ngMultiple Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngReadonly - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as readonly. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngReadonly` directive. - * @example - - - Check me to make text readonly:
- -
- - it('should toggle readonly attr', function() { - expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy(); - }); - -
- * - * @element INPUT - * @param {string} expression Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngSelected - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as selected. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduced the `ngSelected` directive. - * @example - - - Check me to select:
- -
- - it('should select Greetings!', function() { - expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy(); - input('selected').check(); - expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy(); - }); - -
- * - * @element OPTION - * @param {string} expression Angular expression that will be evaluated. - */ - - -var ngAttributeAliasDirectives = {}; - - -// boolean attrs are evaluated -forEach(BOOLEAN_ATTR, function(propName, attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 100, - compile: function() { - return function(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - }; - } - }; - }; -}); - - -// ng-src, ng-href are interpolated -forEach(['src', 'href'], function(attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 99, // it needs to run after the attributes are interpolated - link: function(scope, element, attr) { - attr.$observe(normalized, function(value) { - if (!value) - return; - - attr.$set(attrName, value); - - // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist - // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need - // to set the property as well to achieve the desired effect. - // we use attr[attrName] value since $set can sanitize the url. - if (msie) element.prop(attrName, attr[attrName]); - }); - } - }; - }; -}); - -var nullFormCtrl = { - $addControl: noop, - $removeControl: noop, - $setValidity: noop, - $setDirty: noop -}; - -/** - * @ngdoc object - * @name ng.directive:form.FormController - * - * @property {boolean} $pristine True if user has not interacted with the form yet. - * @property {boolean} $dirty True if user has already interacted with the form. - * @property {boolean} $valid True if all of the containing forms and controls are valid. - * @property {boolean} $invalid True if at least one containing control or form is invalid. - * - * @property {Object} $error Is an object hash, containing references to all invalid controls or - * forms, where: - * - * - keys are validation tokens (error names) — such as `required`, `url` or `email`), - * - values are arrays of controls or forms that are invalid with given error. - * - * @description - * `FormController` keeps track of all its controls and nested forms as well as state of them, - * such as being valid/invalid or dirty/pristine. - * - * Each {@link ng.directive:form form} directive creates an instance - * of `FormController`. - * - */ -//asks for $scope to fool the BC controller module -FormController.$inject = ['$element', '$attrs', '$scope']; -function FormController(element, attrs) { - var form = this, - parentForm = element.parent().controller('form') || nullFormCtrl, - invalidCount = 0, // used to easily determine if we are valid - errors = form.$error = {}; - - // init state - form.$name = attrs.name; - form.$dirty = false; - form.$pristine = true; - form.$valid = true; - form.$invalid = false; - - parentForm.$addControl(form); - - // Setup initial state of the control - element.addClass(PRISTINE_CLASS); - toggleValidCss(true); - - // convenience method for easy toggling of classes - function toggleValidCss(isValid, validationErrorKey) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - element. - removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). - addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); - } - - form.$addControl = function(control) { - if (control.$name && !form.hasOwnProperty(control.$name)) { - form[control.$name] = control; - } - }; - - form.$removeControl = function(control) { - if (control.$name && form[control.$name] === control) { - delete form[control.$name]; - } - forEach(errors, function(queue, validationToken) { - form.$setValidity(validationToken, true, control); - }); - }; - - form.$setValidity = function(validationToken, isValid, control) { - var queue = errors[validationToken]; - - if (isValid) { - if (queue) { - arrayRemove(queue, control); - if (!queue.length) { - invalidCount--; - if (!invalidCount) { - toggleValidCss(isValid); - form.$valid = true; - form.$invalid = false; - } - errors[validationToken] = false; - toggleValidCss(true, validationToken); - parentForm.$setValidity(validationToken, true, form); - } - } - - } else { - if (!invalidCount) { - toggleValidCss(isValid); - } - if (queue) { - if (includes(queue, control)) return; - } else { - errors[validationToken] = queue = []; - invalidCount++; - toggleValidCss(false, validationToken); - parentForm.$setValidity(validationToken, false, form); - } - queue.push(control); - - form.$valid = false; - form.$invalid = true; - } - }; - - form.$setDirty = function() { - element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); - form.$dirty = true; - form.$pristine = false; - parentForm.$setDirty(); - }; - -} - - -/** - * @ngdoc directive - * @name ng.directive:ngForm - * @restrict EAC - * - * @description - * Nestable alias of {@link ng.directive:form `form`} directive. HTML - * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a - * sub-group of controls needs to be determined. - * - * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into - * related scope, under this name. - * - */ - - /** - * @ngdoc directive - * @name ng.directive:form - * @restrict E - * - * @description - * Directive that instantiates - * {@link ng.directive:form.FormController FormController}. - * - * If `name` attribute is specified, the form controller is published onto the current scope under - * this name. - * - * # Alias: {@link ng.directive:ngForm `ngForm`} - * - * In angular forms can be nested. This means that the outer form is valid when all of the child - * forms are valid as well. However browsers do not allow nesting of `
` elements, for this - * reason angular provides {@link ng.directive:ngForm `ngForm`} alias - * which behaves identical to `` but allows form nesting. - * - * - * # CSS classes - * - `ng-valid` Is set if the form is valid. - * - `ng-invalid` Is set if the form is invalid. - * - `ng-pristine` Is set if the form is pristine. - * - `ng-dirty` Is set if the form is dirty. - * - * - * # Submitting a form and preventing default action - * - * Since the role of forms in client-side Angular applications is different than in classical - * roundtrip apps, it is desirable for the browser not to translate the form submission into a full - * page reload that sends the data to the server. Instead some javascript logic should be triggered - * to handle the form submission in application specific way. - * - * For this reason, Angular prevents the default action (form submission to the server) unless the - * `` element has an `action` attribute specified. - * - * You can use one of the following two ways to specify what javascript method should be called when - * a form is submitted: - * - * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element - * - {@link ng.directive:ngClick ngClick} directive on the first - * button or input field of type submit (input[type=submit]) - * - * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This - * is because of the following form submission rules coming from the html spec: - * - * - If a form has only one input field then hitting enter in this field triggers form submit - * (`ngSubmit`) - * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter - * doesn't trigger submit - * - if a form has one or more input fields and one or more buttons or input[type=submit] then - * hitting enter in any of the input fields will trigger the click handler on the *first* button or - * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) - * - * @param {string=} name Name of the form. If specified, the form controller will be published into - * related scope, under this name. - * - * @example - - - - - userType: - Required!
- userType = {{userType}}
- myForm.input.$valid = {{myForm.input.$valid}}
- myForm.input.$error = {{myForm.input.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
- -
- - it('should initialize to model', function() { - expect(binding('userType')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('userType').enter(''); - expect(binding('userType')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
- */ -var formDirectiveFactory = function(isNgForm) { - return ['$timeout', function($timeout) { - var formDirective = { - name: 'form', - restrict: 'E', - controller: FormController, - compile: function() { - return { - pre: function(scope, formElement, attr, controller) { - if (!attr.action) { - // we can't use jq events because if a form is destroyed during submission the default - // action is not prevented. see #1238 - // - // IE 9 is not affected because it doesn't fire a submit event and try to do a full - // page reload if the form was destroyed by submission of the form via a click handler - // on a button in the form. Looks like an IE9 specific bug. - var preventDefaultListener = function(event) { - event.preventDefault - ? event.preventDefault() - : event.returnValue = false; // IE - }; - - addEventListenerFn(formElement[0], 'submit', preventDefaultListener); - - // unregister the preventDefault listener so that we don't not leak memory but in a - // way that will achieve the prevention of the default action. - formElement.bind('$destroy', function() { - $timeout(function() { - removeEventListenerFn(formElement[0], 'submit', preventDefaultListener); - }, 0, false); - }); - } - - var parentFormCtrl = formElement.parent().controller('form'), - alias = attr.name || attr.ngForm; - - if (alias) { - scope[alias] = controller; - } - if (parentFormCtrl) { - formElement.bind('$destroy', function() { - parentFormCtrl.$removeControl(controller); - if (alias) { - scope[alias] = undefined; - } - extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards - }); - } - } - }; - } - }; - - return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective; - }]; -}; - -var formDirective = formDirectiveFactory(); -var ngFormDirective = formDirectiveFactory(true); - -var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; -var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/; -var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; - -var inputType = { - - /** - * @ngdoc inputType - * @name ng.directive:input.text - * - * @description - * Standard HTML text input with angular data binding. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Adds `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
- Single word: - - Required! - - Single word only! - - text = {{text}}
- myForm.input.$valid = {{myForm.input.$valid}}
- myForm.input.$error = {{myForm.input.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
-
-
- - it('should initialize to model', function() { - expect(binding('text')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if multi word', function() { - input('text').enter('hello world'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
- */ - 'text': textInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.number - * - * @description - * Text input with number validation and transformation. Sets the `number` validation - * error if not a valid number. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
- Number: - - Required! - - Not valid number! - value = {{value}}
- myForm.input.$valid = {{myForm.input.$valid}}
- myForm.input.$error = {{myForm.input.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
-
-
- - it('should initialize to model', function() { - expect(binding('value')).toEqual('12'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('value').enter(''); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if over max', function() { - input('value').enter('123'); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
- */ - 'number': numberInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.url - * - * @description - * Text input with URL validation. Sets the `url` validation error key if the content is not a - * valid URL. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
- URL: - - Required! - - Not valid url! - text = {{text}}
- myForm.input.$valid = {{myForm.input.$valid}}
- myForm.input.$error = {{myForm.input.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
- myForm.$error.url = {{!!myForm.$error.url}}
-
-
- - it('should initialize to model', function() { - expect(binding('text')).toEqual('http://google.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if not url', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
- */ - 'url': urlInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.email - * - * @description - * Text input with email validation. Sets the `email` validation error key if not a valid email - * address. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * - * @example - - - -
- Email: - - Required! - - Not valid email! - text = {{text}}
- myForm.input.$valid = {{myForm.input.$valid}}
- myForm.input.$error = {{myForm.input.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
- myForm.$error.email = {{!!myForm.$error.email}}
-
-
- - it('should initialize to model', function() { - expect(binding('text')).toEqual('me@example.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if not email', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
- */ - 'email': emailInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.radio - * - * @description - * HTML radio button. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string} value The value to which the expression should be set when selected. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
- Red
- Green
- Blue
- color = {{color}}
-
-
- - it('should change state', function() { - expect(binding('color')).toEqual('blue'); - - input('color').select('red'); - expect(binding('color')).toEqual('red'); - }); - -
- */ - 'radio': radioInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.checkbox - * - * @description - * HTML checkbox. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngTrueValue The value to which the expression should be set when selected. - * @param {string=} ngFalseValue The value to which the expression should be set when not selected. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
- Value1:
- Value2:
- value1 = {{value1}}
- value2 = {{value2}}
-
-
- - it('should change state', function() { - expect(binding('value1')).toEqual('true'); - expect(binding('value2')).toEqual('YES'); - - input('value1').check(); - input('value2').check(); - expect(binding('value1')).toEqual('false'); - expect(binding('value2')).toEqual('NO'); - }); - -
- */ - 'checkbox': checkboxInputType, - - 'hidden': noop, - 'button': noop, - 'submit': noop, - 'reset': noop -}; - - -function isEmpty(value) { - return isUndefined(value) || value === '' || value === null || value !== value; -} - - -function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { - - var listener = function() { - var value = trim(element.val()); - - if (ctrl.$viewValue !== value) { - scope.$apply(function() { - ctrl.$setViewValue(value); - }); - } - }; - - // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the - // input event on backspace, delete or cut - if ($sniffer.hasEvent('input')) { - element.bind('input', listener); - } else { - var timeout; - - var deferListener = function() { - if (!timeout) { - timeout = $browser.defer(function() { - listener(); - timeout = null; - }); - } - }; - - element.bind('keydown', function(event) { - var key = event.keyCode; - - // ignore - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - - deferListener(); - }); - - // if user paste into input using mouse, we need "change" event to catch it - element.bind('change', listener); - - // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it - if ($sniffer.hasEvent('paste')) { - element.bind('paste cut', deferListener); - } - } - - - ctrl.$render = function() { - element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); - }; - - // pattern validator - var pattern = attr.ngPattern, - patternValidator; - - var validate = function(regexp, value) { - if (isEmpty(value) || regexp.test(value)) { - ctrl.$setValidity('pattern', true); - return value; - } else { - ctrl.$setValidity('pattern', false); - return undefined; - } - }; - - if (pattern) { - if (pattern.match(/^\/(.*)\/$/)) { - pattern = new RegExp(pattern.substr(1, pattern.length - 2)); - patternValidator = function(value) { - return validate(pattern, value) - }; - } else { - patternValidator = function(value) { - var patternObj = scope.$eval(pattern); - - if (!patternObj || !patternObj.test) { - throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj); - } - return validate(patternObj, value); - }; - } - - ctrl.$formatters.push(patternValidator); - ctrl.$parsers.push(patternValidator); - } - - // min length validator - if (attr.ngMinlength) { - var minlength = int(attr.ngMinlength); - var minLengthValidator = function(value) { - if (!isEmpty(value) && value.length < minlength) { - ctrl.$setValidity('minlength', false); - return undefined; - } else { - ctrl.$setValidity('minlength', true); - return value; - } - }; - - ctrl.$parsers.push(minLengthValidator); - ctrl.$formatters.push(minLengthValidator); - } - - // max length validator - if (attr.ngMaxlength) { - var maxlength = int(attr.ngMaxlength); - var maxLengthValidator = function(value) { - if (!isEmpty(value) && value.length > maxlength) { - ctrl.$setValidity('maxlength', false); - return undefined; - } else { - ctrl.$setValidity('maxlength', true); - return value; - } - }; - - ctrl.$parsers.push(maxLengthValidator); - ctrl.$formatters.push(maxLengthValidator); - } -} - -function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - ctrl.$parsers.push(function(value) { - var empty = isEmpty(value); - if (empty || NUMBER_REGEXP.test(value)) { - ctrl.$setValidity('number', true); - return value === '' ? null : (empty ? value : parseFloat(value)); - } else { - ctrl.$setValidity('number', false); - return undefined; - } - }); - - ctrl.$formatters.push(function(value) { - return isEmpty(value) ? '' : '' + value; - }); - - if (attr.min) { - var min = parseFloat(attr.min); - var minValidator = function(value) { - if (!isEmpty(value) && value < min) { - ctrl.$setValidity('min', false); - return undefined; - } else { - ctrl.$setValidity('min', true); - return value; - } - }; - - ctrl.$parsers.push(minValidator); - ctrl.$formatters.push(minValidator); - } - - if (attr.max) { - var max = parseFloat(attr.max); - var maxValidator = function(value) { - if (!isEmpty(value) && value > max) { - ctrl.$setValidity('max', false); - return undefined; - } else { - ctrl.$setValidity('max', true); - return value; - } - }; - - ctrl.$parsers.push(maxValidator); - ctrl.$formatters.push(maxValidator); - } - - ctrl.$formatters.push(function(value) { - - if (isEmpty(value) || isNumber(value)) { - ctrl.$setValidity('number', true); - return value; - } else { - ctrl.$setValidity('number', false); - return undefined; - } - }); -} - -function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var urlValidator = function(value) { - if (isEmpty(value) || URL_REGEXP.test(value)) { - ctrl.$setValidity('url', true); - return value; - } else { - ctrl.$setValidity('url', false); - return undefined; - } - }; - - ctrl.$formatters.push(urlValidator); - ctrl.$parsers.push(urlValidator); -} - -function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var emailValidator = function(value) { - if (isEmpty(value) || EMAIL_REGEXP.test(value)) { - ctrl.$setValidity('email', true); - return value; - } else { - ctrl.$setValidity('email', false); - return undefined; - } - }; - - ctrl.$formatters.push(emailValidator); - ctrl.$parsers.push(emailValidator); -} - -function radioInputType(scope, element, attr, ctrl) { - // make the name unique, if not defined - if (isUndefined(attr.name)) { - element.attr('name', nextUid()); - } - - element.bind('click', function() { - if (element[0].checked) { - scope.$apply(function() { - ctrl.$setViewValue(attr.value); - }); - } - }); - - ctrl.$render = function() { - var value = attr.value; - element[0].checked = (value == ctrl.$viewValue); - }; - - attr.$observe('value', ctrl.$render); -} - -function checkboxInputType(scope, element, attr, ctrl) { - var trueValue = attr.ngTrueValue, - falseValue = attr.ngFalseValue; - - if (!isString(trueValue)) trueValue = true; - if (!isString(falseValue)) falseValue = false; - - element.bind('click', function() { - scope.$apply(function() { - ctrl.$setViewValue(element[0].checked); - }); - }); - - ctrl.$render = function() { - element[0].checked = ctrl.$viewValue; - }; - - ctrl.$formatters.push(function(value) { - return value === trueValue; - }); - - ctrl.$parsers.push(function(value) { - return value ? trueValue : falseValue; - }); -} - - -/** - * @ngdoc directive - * @name ng.directive:textarea - * @restrict E - * - * @description - * HTML textarea element control with angular data-binding. The data-binding and validation - * properties of this element are exactly the same as those of the - * {@link ng.directive:input input element}. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - */ - - -/** - * @ngdoc directive - * @name ng.directive:input - * @restrict E - * - * @description - * HTML input element control with angular data-binding. Input control follows HTML5 input types - * and polyfills the HTML5 validation behavior for older browsers. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {boolean=} ngRequired Sets `required` attribute if set to true - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
-
- User name: - - Required!
- Last name: - - Too short! - - Too long!
-
-
- user = {{user}}
- myForm.userName.$valid = {{myForm.userName.$valid}}
- myForm.userName.$error = {{myForm.userName.$error}}
- myForm.lastName.$valid = {{myForm.lastName.$valid}}
- myForm.lastName.$error = {{myForm.lastName.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
- myForm.$error.minlength = {{!!myForm.$error.minlength}}
- myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
-
-
- - it('should initialize to model', function() { - expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); - }); - - it('should be invalid if empty when required', function() { - input('user.name').enter(''); - expect(binding('user')).toEqual('{"last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('false'); - expect(binding('myForm.$valid')).toEqual('false'); - }); - - it('should be valid if empty when min length is set', function() { - input('user.last').enter(''); - expect(binding('user')).toEqual('{"name":"guest","last":""}'); - expect(binding('myForm.lastName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); - }); - - it('should be invalid if less than required min length', function() { - input('user.last').enter('xx'); - expect(binding('user')).toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/minlength/); - expect(binding('myForm.$valid')).toEqual('false'); - }); - - it('should be invalid if longer than max length', function() { - input('user.last').enter('some ridiculously long name'); - expect(binding('user')) - .toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/maxlength/); - expect(binding('myForm.$valid')).toEqual('false'); - }); - -
- */ -var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { - return { - restrict: 'E', - require: '?ngModel', - link: function(scope, element, attr, ctrl) { - if (ctrl) { - (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer, - $browser); - } - } - }; -}]; - -var VALID_CLASS = 'ng-valid', - INVALID_CLASS = 'ng-invalid', - PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty'; - -/** - * @ngdoc object - * @name ng.directive:ngModel.NgModelController - * - * @property {string} $viewValue Actual string value in the view. - * @property {*} $modelValue The value in the model, that the control is bound to. - * @property {Array.} $parsers Whenever the control reads value from the DOM, it executes - * all of these functions to sanitize / convert the value as well as validate. - * - * @property {Array.} $formatters Whenever the model value changes, it executes all of - * these functions to convert the value as well as validate. - * - * @property {Object} $error An bject hash with all errors as keys. - * - * @property {boolean} $pristine True if user has not interacted with the control yet. - * @property {boolean} $dirty True if user has already interacted with the control. - * @property {boolean} $valid True if there is no error. - * @property {boolean} $invalid True if at least one error on the control. - * - * @description - * - * `NgModelController` provides API for the `ng-model` directive. The controller contains - * services for data-binding, validation, CSS update, value formatting and parsing. It - * specifically does not contain any logic which deals with DOM rendering or listening to - * DOM events. The `NgModelController` is meant to be extended by other directives where, the - * directive provides DOM manipulation and the `NgModelController` provides the data-binding. - * - * This example shows how to use `NgModelController` with a custom control to achieve - * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) - * collaborate together to achieve the desired result. - * - * - - [contenteditable] { - border: 1px solid black; - background-color: white; - min-height: 20px; - } - - .ng-invalid { - border: 1px solid red; - } - - - - angular.module('customControl', []). - directive('contenteditable', function() { - return { - restrict: 'A', // only activate on element attribute - require: '?ngModel', // get a hold of NgModelController - link: function(scope, element, attrs, ngModel) { - if(!ngModel) return; // do nothing if no ng-model - - // Specify how UI should be updated - ngModel.$render = function() { - element.html(ngModel.$viewValue || ''); - }; - - // Listen for change events to enable binding - element.bind('blur keyup change', function() { - scope.$apply(read); - }); - read(); // initialize - - // Write data to the model - function read() { - ngModel.$setViewValue(element.html()); - } - } - }; - }); - - -
-
Change me!
- Required! -
- -
-
- - it('should data-bind and become invalid', function() { - var contentEditable = element('[contenteditable]'); - - expect(contentEditable.text()).toEqual('Change me!'); - input('userContent').enter(''); - expect(contentEditable.text()).toEqual(''); - expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/); - }); - - *
- * - */ -var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', - function($scope, $exceptionHandler, $attr, $element, $parse) { - this.$viewValue = Number.NaN; - this.$modelValue = Number.NaN; - this.$parsers = []; - this.$formatters = []; - this.$viewChangeListeners = []; - this.$pristine = true; - this.$dirty = false; - this.$valid = true; - this.$invalid = false; - this.$name = $attr.name; - - var ngModelGet = $parse($attr.ngModel), - ngModelSet = ngModelGet.assign; - - if (!ngModelSet) { - throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel + - ' (' + startingTag($element) + ')'); - } - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$render - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. - */ - this.$render = noop; - - var parentForm = $element.inheritedData('$formController') || nullFormCtrl, - invalidCount = 0, // used to easily determine if we are valid - $error = this.$error = {}; // keep invalid keys here - - - // Setup initial state of the control - $element.addClass(PRISTINE_CLASS); - toggleValidCss(true); - - // convenience method for easy toggling of classes - function toggleValidCss(isValid, validationErrorKey) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - $element. - removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). - addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); - } - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$setValidity - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Change the validity state, and notifies the form when the control changes validity. (i.e. it - * does not notify form if given validator is already marked as invalid). - * - * This method should be called by validators - i.e. the parser or formatter functions. - * - * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign - * to `$error[validationErrorKey]=isValid` so that it is available for data-binding. - * The `validationErrorKey` should be in camelCase and will get converted into dash-case - * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` - * class and can be bound to as `{{someForm.someControl.$error.myError}}` . - * @param {boolean} isValid Whether the current state is valid (true) or invalid (false). - */ - this.$setValidity = function(validationErrorKey, isValid) { - if ($error[validationErrorKey] === !isValid) return; - - if (isValid) { - if ($error[validationErrorKey]) invalidCount--; - if (!invalidCount) { - toggleValidCss(true); - this.$valid = true; - this.$invalid = false; - } - } else { - toggleValidCss(false); - this.$invalid = true; - this.$valid = false; - invalidCount++; - } - - $error[validationErrorKey] = !isValid; - toggleValidCss(isValid, validationErrorKey); - - parentForm.$setValidity(validationErrorKey, isValid, this); - }; - - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$setViewValue - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Read a value from view. - * - * This method should be called from within a DOM event handler. - * For example {@link ng.directive:input input} or - * {@link ng.directive:select select} directives call it. - * - * It internally calls all `parsers` and if resulted value is valid, updates the model and - * calls all registered change listeners. - * - * @param {string} value Value from the view. - */ - this.$setViewValue = function(value) { - this.$viewValue = value; - - // change to dirty - if (this.$pristine) { - this.$dirty = true; - this.$pristine = false; - $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); - parentForm.$setDirty(); - } - - forEach(this.$parsers, function(fn) { - value = fn(value); - }); - - if (this.$modelValue !== value) { - this.$modelValue = value; - ngModelSet($scope, value); - forEach(this.$viewChangeListeners, function(listener) { - try { - listener(); - } catch(e) { - $exceptionHandler(e); - } - }) - } - }; - - // model -> value - var ctrl = this; - - $scope.$watch(function ngModelWatch() { - var value = ngModelGet($scope); - - // if scope model value and ngModel value are out of sync - if (ctrl.$modelValue !== value) { - - var formatters = ctrl.$formatters, - idx = formatters.length; - - ctrl.$modelValue = value; - while(idx--) { - value = formatters[idx](value); - } - - if (ctrl.$viewValue !== value) { - ctrl.$viewValue = value; - ctrl.$render(); - } - } - }); -}]; - - -/** - * @ngdoc directive - * @name ng.directive:ngModel - * - * @element input - * - * @description - * Is directive that tells Angular to do two-way data binding. It works together with `input`, - * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well. - * - * `ngModel` is responsible for: - * - * - binding the view into the model, which other directives such as `input`, `textarea` or `select` - * require, - * - providing validation behavior (i.e. required, number, email, url), - * - keeping state of the control (valid/invalid, dirty/pristine, validation errors), - * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`), - * - register the control with parent {@link ng.directive:form form}. - * - * For basic examples, how to use `ngModel`, see: - * - * - {@link ng.directive:input input} - * - {@link ng.directive:input.text text} - * - {@link ng.directive:input.checkbox checkbox} - * - {@link ng.directive:input.radio radio} - * - {@link ng.directive:input.number number} - * - {@link ng.directive:input.email email} - * - {@link ng.directive:input.url url} - * - {@link ng.directive:select select} - * - {@link ng.directive:textarea textarea} - * - */ -var ngModelDirective = function() { - return { - require: ['ngModel', '^?form'], - controller: NgModelController, - link: function(scope, element, attr, ctrls) { - // notify others, especially parent forms - - var modelCtrl = ctrls[0], - formCtrl = ctrls[1] || nullFormCtrl; - - formCtrl.$addControl(modelCtrl); - - element.bind('$destroy', function() { - formCtrl.$removeControl(modelCtrl); - }); - } - }; -}; - - -/** - * @ngdoc directive - * @name ng.directive:ngChange - * @restrict E - * - * @description - * Evaluate given expression when user changes the input. - * The expression is not evaluated when the value change is coming from the model. - * - * Note, this directive requires `ngModel` to be present. - * - * @element input - * - * @example - * - * - * - *
- * - * - *
- * debug = {{confirmed}}
- * counter = {{counter}} - *
- *
- * - * it('should evaluate the expression if changing from view', function() { - * expect(binding('counter')).toEqual('0'); - * element('#ng-change-example1').click(); - * expect(binding('counter')).toEqual('1'); - * expect(binding('confirmed')).toEqual('true'); - * }); - * - * it('should not evaluate the expression if changing from model', function() { - * element('#ng-change-example2').click(); - * expect(binding('counter')).toEqual('0'); - * expect(binding('confirmed')).toEqual('true'); - * }); - * - *
- */ -var ngChangeDirective = valueFn({ - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - ctrl.$viewChangeListeners.push(function() { - scope.$eval(attr.ngChange); - }); - } -}); - - -var requiredDirective = function() { - return { - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - attr.required = true; // force truthy in case we are on non input element - - var validator = function(value) { - if (attr.required && (isEmpty(value) || value === false)) { - ctrl.$setValidity('required', false); - return; - } else { - ctrl.$setValidity('required', true); - return value; - } - }; - - ctrl.$formatters.push(validator); - ctrl.$parsers.unshift(validator); - - attr.$observe('required', function() { - validator(ctrl.$viewValue); - }); - } - }; -}; - - -/** - * @ngdoc directive - * @name ng.directive:ngList - * - * @description - * Text input that converts between comma-separated string into an array of strings. - * - * @element input - * @param {string=} ngList optional delimiter that should be used to split the value. If - * specified in form `/something/` then the value will be converted into a regular expression. - * - * @example - - - -
- List: - - Required! - names = {{names}}
- myForm.namesInput.$valid = {{myForm.namesInput.$valid}}
- myForm.namesInput.$error = {{myForm.namesInput.$error}}
- myForm.$valid = {{myForm.$valid}}
- myForm.$error.required = {{!!myForm.$error.required}}
-
-
- - it('should initialize to model', function() { - expect(binding('names')).toEqual('["igor","misko","vojta"]'); - expect(binding('myForm.namesInput.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('names').enter(''); - expect(binding('names')).toEqual('[]'); - expect(binding('myForm.namesInput.$valid')).toEqual('false'); - }); - -
- */ -var ngListDirective = function() { - return { - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - var match = /\/(.*)\//.exec(attr.ngList), - separator = match && new RegExp(match[1]) || attr.ngList || ','; - - var parse = function(viewValue) { - var list = []; - - if (viewValue) { - forEach(viewValue.split(separator), function(value) { - if (value) list.push(trim(value)); - }); - } - - return list; - }; - - ctrl.$parsers.push(parse); - ctrl.$formatters.push(function(value) { - if (isArray(value)) { - return value.join(', '); - } - - return undefined; - }); - } - }; -}; - - -var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; - -var ngValueDirective = function() { - return { - priority: 100, - compile: function(tpl, tplAttr) { - if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { - return function(scope, elm, attr) { - attr.$set('value', scope.$eval(attr.ngValue)); - }; - } else { - return function(scope, elm, attr) { - scope.$watch(attr.ngValue, function valueWatchAction(value) { - attr.$set('value', value, false); - }); - }; - } - } - }; -}; - -/** - * @ngdoc directive - * @name ng.directive:ngBind - * - * @description - * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element - * with the value of a given expression, and to update the text content when the value of that - * expression changes. - * - * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like - * `{{ expression }}` which is similar but less verbose. - * - * One scenario in which the use of `ngBind` is preferred over `{{ expression }}` binding is when - * it's desirable to put bindings into template that is momentarily displayed by the browser in its - * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the - * bindings invisible to the user while the page is loading. - * - * An alternative solution to this problem would be using the - * {@link ng.directive:ngCloak ngCloak} directive. - * - * - * @element ANY - * @param {expression} ngBind {@link guide/expression Expression} to evaluate. - * - * @example - * Enter a name in the Live Preview text box; the greeting below the text box changes instantly. - - - -
- Enter name:
- Hello ! -
-
- - it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); - }); - -
- */ -var ngBindDirective = ngDirective(function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.ngBind); - scope.$watch(attr.ngBind, function ngBindWatchAction(value) { - element.text(value == undefined ? '' : value); - }); -}); - - -/** - * @ngdoc directive - * @name ng.directive:ngBindTemplate - * - * @description - * The `ngBindTemplate` directive specifies that the element - * text should be replaced with the template in ngBindTemplate. - * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}` - * expressions. (This is required since some HTML elements - * can not have SPAN elements such as TITLE, or OPTION to name a few.) - * - * @element ANY - * @param {string} ngBindTemplate template of form - * {{ expression }} to eval. - * - * @example - * Try it here: enter text in text box and watch the greeting change. - - - -
- Salutation:
- Name:
-

-       
-
- - it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('salutation')). - toBe('Hello'); - expect(using('.doc-example-live').binding('name')). - toBe('World'); - using('.doc-example-live').input('salutation').enter('Greetings'); - using('.doc-example-live').input('name').enter('user'); - expect(using('.doc-example-live').binding('salutation')). - toBe('Greetings'); - expect(using('.doc-example-live').binding('name')). - toBe('user'); - }); - -
- */ -var ngBindTemplateDirective = ['$interpolate', function($interpolate) { - return function(scope, element, attr) { - // TODO: move this to scenario runner - var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); - element.addClass('ng-binding').data('$binding', interpolateFn); - attr.$observe('ngBindTemplate', function(value) { - element.text(value); - }); - } -}]; - - -/** - * @ngdoc directive - * @name ng.directive:ngBindHtmlUnsafe - * - * @description - * Creates a binding that will innerHTML the result of evaluating the `expression` into the current - * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if - * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too - * restrictive and when you absolutely trust the source of the content you are binding to. - * - * See {@link ngSanitize.$sanitize $sanitize} docs for examples. - * - * @element ANY - * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate. - */ -var ngBindHtmlUnsafeDirective = [function() { - return function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe); - scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) { - element.html(value || ''); - }); - }; -}]; - -function classDirective(name, selector) { - name = 'ngClass' + name; - return ngDirective(function(scope, element, attr) { - var oldVal = undefined; - - scope.$watch(attr[name], ngClassWatchAction, true); - - attr.$observe('class', function(value) { - var ngClass = scope.$eval(attr[name]); - ngClassWatchAction(ngClass, ngClass); - }); - - - if (name !== 'ngClass') { - scope.$watch('$index', function($index, old$index) { - var mod = $index & 1; - if (mod !== old$index & 1) { - if (mod === selector) { - addClass(scope.$eval(attr[name])); - } else { - removeClass(scope.$eval(attr[name])); - } - } - }); - } - - - function ngClassWatchAction(newVal) { - if (selector === true || scope.$index % 2 === selector) { - if (oldVal && !equals(newVal,oldVal)) { - removeClass(oldVal); - } - addClass(newVal); - } - oldVal = copy(newVal); - } - - - function removeClass(classVal) { - if (isObject(classVal) && !isArray(classVal)) { - classVal = map(classVal, function(v, k) { if (v) return k }); - } - element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal); - } - - - function addClass(classVal) { - if (isObject(classVal) && !isArray(classVal)) { - classVal = map(classVal, function(v, k) { if (v) return k }); - } - if (classVal) { - element.addClass(isArray(classVal) ? classVal.join(' ') : classVal); - } - } - }); -} - -/** - * @ngdoc directive - * @name ng.directive:ngClass - * - * @description - * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an - * expression that represents all classes to be added. - * - * The directive won't add duplicate classes if a particular class was already set. - * - * When the expression changes, the previously added classes are removed and only then the - * new classes are added. - * - * @element ANY - * @param {expression} ngClass {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class - * names, an array, or a map of class names to boolean values. - * - * @example - - - - -
- Sample Text -
- - .my-class { - color: red; - } - - - it('should check ng-class', function() { - expect(element('.doc-example-live span').prop('className')).not(). - toMatch(/my-class/); - - using('.doc-example-live').element(':button:first').click(); - - expect(element('.doc-example-live span').prop('className')). - toMatch(/my-class/); - - using('.doc-example-live').element(':button:last').click(); - - expect(element('.doc-example-live span').prop('className')).not(). - toMatch(/my-class/); - }); - -
- */ -var ngClassDirective = classDirective('', true); - -/** - * @ngdoc directive - * @name ng.directive:ngClassOdd - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except it works in - * conjunction with `ngRepeat` and takes affect only on odd (even) rows. - * - * This directive can be applied only within a scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class names or an array. - * - * @example - - -
    -
  1. - - {{name}} - -
  2. -
-
- - .odd { - color: red; - } - .even { - color: blue; - } - - - it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). - toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). - toMatch(/even/); - }); - -
- */ -var ngClassOddDirective = classDirective('Odd', 0); - -/** - * @ngdoc directive - * @name ng.directive:ngClassEven - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except it works in - * conjunction with `ngRepeat` and takes affect only on odd (even) rows. - * - * This directive can be applied only within a scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The - * result of the evaluation can be a string representing space delimited class names or an array. - * - * @example - - -
    -
  1. - - {{name}}       - -
  2. -
-
- - .odd { - color: red; - } - .even { - color: blue; - } - - - it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). - toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). - toMatch(/even/); - }); - -
- */ -var ngClassEvenDirective = classDirective('Even', 1); - -/** - * @ngdoc directive - * @name ng.directive:ngCloak - * - * @description - * The `ngCloak` directive is used to prevent the Angular html template from being briefly - * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this - * directive to avoid the undesirable flicker effect caused by the html template display. - * - * The directive can be applied to the `` element, but typically a fine-grained application is - * prefered in order to benefit from progressive rendering of the browser view. - * - * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and - * `angular.min.js` files. Following is the css rule: - * - *
- * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- *   display: none;
- * }
- * 
- * - * When this css rule is loaded by the browser, all html elements (including their children) that - * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive - * during the compilation of the template it deletes the `ngCloak` element attribute, which - * makes the compiled element visible. - * - * For the best result, `angular.js` script must be loaded in the head section of the html file; - * alternatively, the css rule (above) must be included in the external stylesheet of the - * application. - * - * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they - * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css - * class `ngCloak` in addition to `ngCloak` directive as shown in the example below. - * - * @element ANY - * - * @example - - -
{{ 'hello' }}
-
{{ 'hello IE7' }}
-
- - it('should remove the template directive and css class', function() { - expect(element('.doc-example-live #template1').attr('ng-cloak')). - not().toBeDefined(); - expect(element('.doc-example-live #template2').attr('ng-cloak')). - not().toBeDefined(); - }); - -
- * - */ -var ngCloakDirective = ngDirective({ - compile: function(element, attr) { - attr.$set('ngCloak', undefined); - element.removeClass('ng-cloak'); - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngController - * - * @description - * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular - * supports the principles behind the Model-View-Controller design pattern. - * - * MVC components in angular: - * - * * Model — The Model is data in scope properties; scopes are attached to the DOM. - * * View — The template (HTML with data bindings) is rendered into the View. - * * Controller — The `ngController` directive specifies a Controller class; the class has - * methods that typically express the business logic behind the application. - * - * Note that an alternative way to define controllers is via the {@link ng.$route $route} service. - * - * @element ANY - * @scope - * @param {expression} ngController Name of a globally accessible constructor function or an - * {@link guide/expression expression} that on the current scope evaluates to a - * constructor function. - * - * @example - * Here is a simple form for editing user contact information. Adding, removing, clearing, and - * greeting are methods declared on the controller (see source tab). These methods can - * easily be called from the angular markup. Notice that the scope becomes the `this` for the - * controller's instance. This allows for easy access to the view data from the controller. Also - * notice that any changes to the data are automatically reflected in the View without the need - * for a manual update. - - - -
- Name: - [ greet ]
- Contact: -
    -
  • - - - [ clear - | X ] -
  • -
  • [ add ]
  • -
-
-
- - it('should check controller', function() { - expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); - expect(element('.doc-example-live li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('.doc-example-live li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('.doc-example-live li:first a:contains("clear")').click(); - expect(element('.doc-example-live li:first input').val()).toBe(''); - - element('.doc-example-live li:last a:contains("add")').click(); - expect(element('.doc-example-live li:nth-child(3) input').val()) - .toBe('yourname@example.org'); - }); - -
- */ -var ngControllerDirective = [function() { - return { - scope: true, - controller: '@' - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngCsp - * @priority 1000 - * - * @element html - * @description - * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. - * - * This is necessary when developing things like Google Chrome Extensions. - * - * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). - * For us to be compatible, we just need to implement the "getterFn" in $parse without violating - * any of these restrictions. - * - * AngularJS uses `Function(string)` generated functions as a speed optimization. By applying `ngCsp` - * it is be possible to opt into the CSP compatible mode. When this mode is on AngularJS will - * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will - * be raised. - * - * In order to use this feature put `ngCsp` directive on the root element of the application. - * - * @example - * This example shows how to apply the `ngCsp` directive to the `html` tag. -
-     
-     
-     ...
-     ...
-     
-   
- */ - -var ngCspDirective = ['$sniffer', function($sniffer) { - return { - priority: 1000, - compile: function() { - $sniffer.csp = true; - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngClick - * - * @description - * The ngClick allows you to specify custom behavior when - * element is clicked. - * - * @element ANY - * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon - * click. (Event object is available as `$event`) - * - * @example - - - - count: {{count}} - - - it('should check ng-click', function() { - expect(binding('count')).toBe('0'); - element('.doc-example-live :button').click(); - expect(binding('count')).toBe('1'); - }); - - - */ -/* - * A directive that allows creation of custom onclick handlers that are defined as angular - * expressions and are compiled and executed within the current scope. - * - * Events that are handled via these handler are always configured not to propagate further. - */ -var ngEventDirectives = {}; -forEach( - 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '), - function(name) { - var directiveName = directiveNormalize('ng-' + name); - ngEventDirectives[directiveName] = ['$parse', function($parse) { - return function(scope, element, attr) { - var fn = $parse(attr[directiveName]); - element.bind(lowercase(name), function(event) { - scope.$apply(function() { - fn(scope, {$event:event}); - }); - }); - }; - }]; - } -); - -/** - * @ngdoc directive - * @name ng.directive:ngDblclick - * - * @description - * The `ngDblclick` directive allows you to specify custom behavior on dblclick event. - * - * @element ANY - * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon - * dblclick. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMousedown - * - * @description - * The ngMousedown directive allows you to specify custom behavior on mousedown event. - * - * @element ANY - * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon - * mousedown. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseup - * - * @description - * Specify custom behavior on mouseup event. - * - * @element ANY - * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon - * mouseup. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - -/** - * @ngdoc directive - * @name ng.directive:ngMouseover - * - * @description - * Specify custom behavior on mouseover event. - * - * @element ANY - * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon - * mouseover. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseenter - * - * @description - * Specify custom behavior on mouseenter event. - * - * @element ANY - * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon - * mouseenter. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseleave - * - * @description - * Specify custom behavior on mouseleave event. - * - * @element ANY - * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon - * mouseleave. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMousemove - * - * @description - * Specify custom behavior on mousemove event. - * - * @element ANY - * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon - * mousemove. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngSubmit - * - * @description - * Enables binding angular expressions to onsubmit events. - * - * Additionally it prevents the default action (which for form means sending the request to the - * server and reloading the current page). - * - * @element form - * @param {expression} ngSubmit {@link guide/expression Expression} to eval. - * - * @example - - - -
- Enter text and hit enter: - - -
list={{list}}
-
-
- - it('should check ng-submit', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - expect(input('text').val()).toBe(''); - }); - it('should ignore empty strings', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - }); - -
- */ -var ngSubmitDirective = ngDirective(function(scope, element, attrs) { - element.bind('submit', function() { - scope.$apply(attrs.ngSubmit); - }); -}); - -/** - * @ngdoc directive - * @name ng.directive:ngInclude - * @restrict ECA - * - * @description - * Fetches, compiles and includes an external HTML fragment. - * - * Keep in mind that Same Origin Policy applies to included resources - * (e.g. ngInclude won't work for cross-domain requests on all browsers and for - * file:// access on some browsers). - * - * @scope - * - * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, - * make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`. - * @param {string=} onload Expression to evaluate when a new partial is loaded. - * - * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll - * $anchorScroll} to scroll the viewport after the content is loaded. - * - * - If the attribute is not set, disable scrolling. - * - If the attribute is set without value, enable scrolling. - * - Otherwise enable scrolling only if the expression evaluates to truthy value. - * - * @example - - -
- - url of the template: {{template.url}} -
-
-
-
- - function Ctrl($scope) { - $scope.templates = - [ { name: 'template1.html', url: 'template1.html'} - , { name: 'template2.html', url: 'template2.html'} ]; - $scope.template = $scope.templates[0]; - } - - - Content of template1.html - - - Content of template2.html - - - it('should load template1.html', function() { - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template1.html/); - }); - it('should load template2.html', function() { - select('template').option('1'); - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template2.html/); - }); - it('should change to blank', function() { - select('template').option(''); - expect(element('.doc-example-live [ng-include]').text()).toEqual(''); - }); - -
- */ - - -/** - * @ngdoc event - * @name ng.directive:ngInclude#$includeContentLoaded - * @eventOf ng.directive:ngInclude - * @eventType emit on the current ngInclude scope - * @description - * Emitted every time the ngInclude content is reloaded. - */ -var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', - function($http, $templateCache, $anchorScroll, $compile) { - return { - restrict: 'ECA', - terminal: true, - compile: function(element, attr) { - var srcExp = attr.ngInclude || attr.src, - onloadExp = attr.onload || '', - autoScrollExp = attr.autoscroll; - - return function(scope, element) { - var changeCounter = 0, - childScope; - - var clearContent = function() { - if (childScope) { - childScope.$destroy(); - childScope = null; - } - - element.html(''); - }; - - scope.$watch(srcExp, function ngIncludeWatchAction(src) { - var thisChangeId = ++changeCounter; - - if (src) { - $http.get(src, {cache: $templateCache}).success(function(response) { - if (thisChangeId !== changeCounter) return; - - if (childScope) childScope.$destroy(); - childScope = scope.$new(); - - element.html(response); - $compile(element.contents())(childScope); - - if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); - } - - childScope.$emit('$includeContentLoaded'); - scope.$eval(onloadExp); - }).error(function() { - if (thisChangeId === changeCounter) clearContent(); - }); - } else clearContent(); - }); - }; - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngInit - * - * @description - * The `ngInit` directive specifies initialization tasks to be executed - * before the template enters execution mode during bootstrap. - * - * @element ANY - * @param {expression} ngInit {@link guide/expression Expression} to eval. - * - * @example - - -
- {{greeting}} {{person}}! -
-
- - it('should check greeting', function() { - expect(binding('greeting')).toBe('Hello'); - expect(binding('person')).toBe('World'); - }); - -
- */ -var ngInitDirective = ngDirective({ - compile: function() { - return { - pre: function(scope, element, attrs) { - scope.$eval(attrs.ngInit); - } - } - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngNonBindable - * @priority 1000 - * - * @description - * Sometimes it is necessary to write code which looks like bindings but which should be left alone - * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML. - * - * @element ANY - * - * @example - * In this example there are two location where a simple binding (`{{}}`) is present, but the one - * wrapped in `ngNonBindable` is left alone. - * - * @example - - -
Normal: {{1 + 2}}
-
Ignored: {{1 + 2}}
-
- - it('should check ng-non-bindable', function() { - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); - }); - -
- */ -var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); - -/** - * @ngdoc directive - * @name ng.directive:ngPluralize - * @restrict EA - * - * @description - * # Overview - * `ngPluralize` is a directive that displays messages according to en-US localization rules. - * These rules are bundled with angular.js and the rules can be overridden - * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive - * by specifying the mappings between - * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - * plural categories} and the strings to be displayed. - * - * # Plural categories and explicit number rules - * There are two - * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - * plural categories} in Angular's default en-US locale: "one" and "other". - * - * While a pural category may match many numbers (for example, in en-US locale, "other" can match - * any number that is not 1), an explicit number rule can only match one number. For example, the - * explicit number rule for "3" matches the number 3. You will see the use of plural categories - * and explicit number rules throughout later parts of this documentation. - * - * # Configuring ngPluralize - * You configure ngPluralize by providing 2 attributes: `count` and `when`. - * You can also provide an optional attribute, `offset`. - * - * The value of the `count` attribute can be either a string or an {@link guide/expression - * Angular expression}; these are evaluated on the current scope for its bound value. - * - * The `when` attribute specifies the mappings between plural categories and the actual - * string to be displayed. The value of the attribute should be a JSON object so that Angular - * can interpret it correctly. - * - * The following example shows how to configure ngPluralize: - * - *
- * 
- * 
- *
- * - * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not - * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" - * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for - * other numbers, for example 12, so that instead of showing "12 people are viewing", you can - * show "a dozen people are viewing". - * - * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted - * into pluralized strings. In the previous example, Angular will replace `{}` with - * `{{personCount}}`. The closed braces `{}` is a placeholder - * for {{numberExpression}}. - * - * # Configuring ngPluralize with offset - * The `offset` attribute allows further customization of pluralized text, which can result in - * a better user experience. For example, instead of the message "4 people are viewing this document", - * you might display "John, Kate and 2 others are viewing this document". - * The offset attribute allows you to offset a number by any desired value. - * Let's take a look at an example: - * - *
- * 
- * 
- * 
- * - * Notice that we are still using two plural categories(one, other), but we added - * three explicit number rules 0, 1 and 2. - * When one person, perhaps John, views the document, "John is viewing" will be shown. - * When three people view the document, no explicit number rule is found, so - * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. - * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing" - * is shown. - * - * Note that when you specify offsets, you must provide explicit number rules for - * numbers from 0 up to and including the offset. If you use an offset of 3, for example, - * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for - * plural categories "one" and "other". - * - * @param {string|expression} count The variable to be bounded to. - * @param {string} when The mapping between plural category to its correspoding strings. - * @param {number=} offset Offset to deduct from the total number. - * - * @example - - - -
- Person 1:
- Person 2:
- Number of People:
- - - Without Offset: - -
- - - With Offset(2): - - -
-
- - it('should show correct pluralized string', function() { - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('1 person is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor is viewing.'); - - using('.doc-example-live').input('personCount').enter('0'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('Nobody is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Nobody is viewing.'); - - using('.doc-example-live').input('personCount').enter('2'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('2 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor and Misko are viewing.'); - - using('.doc-example-live').input('personCount').enter('3'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('3 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and one other person are viewing.'); - - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('4 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - }); - - it('should show data-binded names', function() { - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - - using('.doc-example-live').input('person1').enter('Di'); - using('.doc-example-live').input('person2').enter('Vojta'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Di, Vojta and 2 other people are viewing.'); - }); - -
- */ -var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { - var BRACE = /{}/g; - return { - restrict: 'EA', - link: function(scope, element, attr) { - var numberExp = attr.count, - whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs - offset = attr.offset || 0, - whens = scope.$eval(whenExp), - whensExpFns = {}, - startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(); - - forEach(whens, function(expression, key) { - whensExpFns[key] = - $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' + - offset + endSymbol)); - }); - - scope.$watch(function ngPluralizeWatch() { - var value = parseFloat(scope.$eval(numberExp)); - - if (!isNaN(value)) { - //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise, - //check it against pluralization rules in $locale service - if (!(value in whens)) value = $locale.pluralCat(value - offset); - return whensExpFns[value](scope, element, true); - } else { - return ''; - } - }, function ngPluralizeWatchAction(newVal) { - element.text(newVal); - }); - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngRepeat - * - * @description - * The `ngRepeat` directive instantiates a template once per item from a collection. Each template - * instance gets its own scope, where the given loop variable is set to the current collection item, - * and `$index` is set to the item index or key. - * - * Special properties are exposed on the local scope of each template instance, including: - * - * * `$index` – `{number}` – iterator offset of the repeated element (0..length-1) - * * `$first` – `{boolean}` – true if the repeated element is first in the iterator. - * * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator. - * * `$last` – `{boolean}` – true if the repeated element is last in the iterator. - * - * - * @element ANY - * @scope - * @priority 1000 - * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two - * formats are currently supported: - * - * * `variable in expression` – where variable is the user defined loop variable and `expression` - * is a scope expression giving the collection to enumerate. - * - * For example: `track in cd.tracks`. - * - * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, - * and `expression` is the scope expression giving the collection to enumerate. - * - * For example: `(name, age) in {'adam':10, 'amalie':12}`. - * - * @example - * This example initializes the scope to a list of names and - * then uses `ngRepeat` to display every person: - - -
- I have {{friends.length}} friends. They are: -
    -
  • - [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. -
  • -
-
-
- - it('should check ng-repeat', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Mary","28"]); - }); - -
- */ -var ngRepeatDirective = ngDirective({ - transclude: 'element', - priority: 1000, - terminal: true, - compile: function(element, attr, linker) { - return function(scope, iterStartElement, attr){ - var expression = attr.ngRepeat; - var match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/), - lhs, rhs, valueIdent, keyIdent; - if (! match) { - throw Error("Expected ngRepeat in form of '_item_ in _collection_' but got '" + - expression + "'."); - } - lhs = match[1]; - rhs = match[2]; - match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/); - if (!match) { - throw Error("'item' in 'item in collection' should be identifier or (key, value) but got '" + - lhs + "'."); - } - valueIdent = match[3] || match[1]; - keyIdent = match[2]; - - // Store a list of elements from previous run. This is a hash where key is the item from the - // iterator, and the value is an array of objects with following properties. - // - scope: bound scope - // - element: previous element. - // - index: position - // We need an array of these objects since the same object can be returned from the iterator. - // We expect this to be a rare case. - var lastOrder = new HashQueueMap(); - - scope.$watch(function ngRepeatWatch(scope){ - var index, length, - collection = scope.$eval(rhs), - cursor = iterStartElement, // current position of the node - // Same as lastOrder but it has the current state. It will become the - // lastOrder on the next iteration. - nextOrder = new HashQueueMap(), - arrayBound, - childScope, - key, value, // key/value of iteration - array, - last; // last object information {scope, element, index} - - - - if (!isArray(collection)) { - // if object, extract keys, sort them and use to determine order of iteration over obj props - array = []; - for(key in collection) { - if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { - array.push(key); - } - } - array.sort(); - } else { - array = collection || []; - } - - arrayBound = array.length-1; - - // we are not using forEach for perf reasons (trying to avoid #call) - for (index = 0, length = array.length; index < length; index++) { - key = (collection === array) ? index : array[index]; - value = collection[key]; - - last = lastOrder.shift(value); - - if (last) { - // if we have already seen this object, then we need to reuse the - // associated scope/element - childScope = last.scope; - nextOrder.push(value, last); - - if (index === last.index) { - // do nothing - cursor = last.element; - } else { - // existing item which got moved - last.index = index; - // This may be a noop, if the element is next, but I don't know of a good way to - // figure this out, since it would require extra DOM access, so let's just hope that - // the browsers realizes that it is noop, and treats it as such. - cursor.after(last.element); - cursor = last.element; - } - } else { - // new item which we don't know about - childScope = scope.$new(); - } - - childScope[valueIdent] = value; - if (keyIdent) childScope[keyIdent] = key; - childScope.$index = index; - - childScope.$first = (index === 0); - childScope.$last = (index === arrayBound); - childScope.$middle = !(childScope.$first || childScope.$last); - - if (!last) { - linker(childScope, function(clone){ - cursor.after(clone); - last = { - scope: childScope, - element: (cursor = clone), - index: index - }; - nextOrder.push(value, last); - }); - } - } - - //shrink children - for (key in lastOrder) { - if (lastOrder.hasOwnProperty(key)) { - array = lastOrder[key]; - while(array.length) { - value = array.pop(); - value.element.remove(); - value.scope.$destroy(); - } - } - } - - lastOrder = nextOrder; - }); - }; - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngShow - * - * @description - * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML) - * conditionally. - * - * @element ANY - * @param {expression} ngShow If the {@link guide/expression expression} is truthy - * then the element is shown or hidden respectively. - * - * @example - - - Click me:
- Show: I show up when your checkbox is checked.
- Hide: I hide when your checkbox is checked. -
- - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); - -
- */ -//TODO(misko): refactor to remove element from the DOM -var ngShowDirective = ngDirective(function(scope, element, attr){ - scope.$watch(attr.ngShow, function ngShowWatchAction(value){ - element.css('display', toBoolean(value) ? '' : 'none'); - }); -}); - - -/** - * @ngdoc directive - * @name ng.directive:ngHide - * - * @description - * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML) - * conditionally. - * - * @element ANY - * @param {expression} ngHide If the {@link guide/expression expression} is truthy then - * the element is shown or hidden respectively. - * - * @example - - - Click me:
- Show: I show up when you checkbox is checked?
- Hide: I hide when you checkbox is checked? -
- - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); - -
- */ -//TODO(misko): refactor to remove element from the DOM -var ngHideDirective = ngDirective(function(scope, element, attr){ - scope.$watch(attr.ngHide, function ngHideWatchAction(value){ - element.css('display', toBoolean(value) ? 'none' : ''); - }); -}); - -/** - * @ngdoc directive - * @name ng.directive:ngStyle - * - * @description - * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. - * - * @element ANY - * @param {expression} ngStyle {@link guide/expression Expression} which evals to an - * object whose keys are CSS style names and values are corresponding values for those CSS - * keys. - * - * @example - - - - -
- Sample Text -
myStyle={{myStyle}}
-
- - span { - color: black; - } - - - it('should check ng-style', function() { - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - }); - -
- */ -var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { - if (oldStyles && (newStyles !== oldStyles)) { - forEach(oldStyles, function(val, style) { element.css(style, '');}); - } - if (newStyles) element.css(newStyles); - }, true); -}); - -/** - * @ngdoc directive - * @name ng.directive:ngSwitch - * @restrict EA - * - * @description - * Conditionally change the DOM structure. - * - * @usage - * - * ... - * ... - * ... - * ... - * - * - * @scope - * @param {*} ngSwitch|on expression to match against ng-switch-when. - * @paramDescription - * On child elments add: - * - * * `ngSwitchWhen`: the case statement to match against. If match then this - * case will be displayed. - * * `ngSwitchDefault`: the default case when no other casses match. - * - * @example - - - -
- - selection={{selection}} -
-
-
Settings Div
- Home Span - default -
-
-
- - it('should start in settings', function() { - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/); - }); - it('should change to home', function() { - select('selection').option('home'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/); - }); - it('should select deafault', function() { - select('selection').option('other'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/); - }); - -
- */ -var NG_SWITCH = 'ng-switch'; -var ngSwitchDirective = valueFn({ - restrict: 'EA', - require: 'ngSwitch', - // asks for $scope to fool the BC controller module - controller: ['$scope', function ngSwitchController() { - this.cases = {}; - }], - link: function(scope, element, attr, ctrl) { - var watchExpr = attr.ngSwitch || attr.on, - selectedTransclude, - selectedElement, - selectedScope; - - scope.$watch(watchExpr, function ngSwitchWatchAction(value) { - if (selectedElement) { - selectedScope.$destroy(); - selectedElement.remove(); - selectedElement = selectedScope = null; - } - if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) { - scope.$eval(attr.change); - selectedScope = scope.$new(); - selectedTransclude(selectedScope, function(caseElement) { - selectedElement = caseElement; - element.append(caseElement); - }); - } - }); - } -}); - -var ngSwitchWhenDirective = ngDirective({ - transclude: 'element', - priority: 500, - require: '^ngSwitch', - compile: function(element, attrs, transclude) { - return function(scope, element, attr, ctrl) { - ctrl.cases['!' + attrs.ngSwitchWhen] = transclude; - }; - } -}); - -var ngSwitchDefaultDirective = ngDirective({ - transclude: 'element', - priority: 500, - require: '^ngSwitch', - compile: function(element, attrs, transclude) { - return function(scope, element, attr, ctrl) { - ctrl.cases['?'] = transclude; - }; - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngTransclude - * - * @description - * Insert the transcluded DOM here. - * - * @element ANY - * - * @example - - - -
-
-
- {{text}} -
-
- - it('should have transcluded', function() { - input('title').enter('TITLE'); - input('text').enter('TEXT'); - expect(binding('title')).toEqual('TITLE'); - expect(binding('text')).toEqual('TEXT'); - }); - -
- * - */ -var ngTranscludeDirective = ngDirective({ - controller: ['$transclude', '$element', function($transclude, $element) { - $transclude(function(clone) { - $element.append(clone); - }); - }] -}); - -/** - * @ngdoc directive - * @name ng.directive:ngView - * @restrict ECA - * - * @description - * # Overview - * `ngView` is a directive that complements the {@link ng.$route $route} service by - * including the rendered template of the current route into the main layout (`index.html`) file. - * Every time the current route changes, the included view changes with it according to the - * configuration of the `$route` service. - * - * @scope - * @example - - -
- Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
- -
-
- -
$location.path() = {{$location.path()}}
-
$route.current.templateUrl = {{$route.current.templateUrl}}
-
$route.current.params = {{$route.current.params}}
-
$route.current.scope.name = {{$route.current.scope.name}}
-
$routeParams = {{$routeParams}}
-
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
- Chapter Id: {{params.chapterId}} -
- - - angular.module('ngView', [], function($routeProvider, $locationProvider) { - $routeProvider.when('/Book/:bookId', { - templateUrl: 'book.html', - controller: BookCntl - }); - $routeProvider.when('/Book/:bookId/ch/:chapterId', { - templateUrl: 'chapter.html', - controller: ChapterCntl - }); - - // configure html5 to get links working on jsfiddle - $locationProvider.html5Mode(true); - }); - - function MainCntl($scope, $route, $routeParams, $location) { - $scope.$route = $route; - $scope.$location = $location; - $scope.$routeParams = $routeParams; - } - - function BookCntl($scope, $routeParams) { - $scope.name = "BookCntl"; - $scope.params = $routeParams; - } - - function ChapterCntl($scope, $routeParams) { - $scope.name = "ChapterCntl"; - $scope.params = $routeParams; - } - - - - it('should load and compile correct template', function() { - element('a:contains("Moby: Ch1")').click(); - var content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: ChapterCntl/); - expect(content).toMatch(/Book Id\: Moby/); - expect(content).toMatch(/Chapter Id\: 1/); - - element('a:contains("Scarlet")').click(); - content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: BookCntl/); - expect(content).toMatch(/Book Id\: Scarlet/); - }); - -
- */ - - -/** - * @ngdoc event - * @name ng.directive:ngView#$viewContentLoaded - * @eventOf ng.directive:ngView - * @eventType emit on the current ngView scope - * @description - * Emitted every time the ngView content is reloaded. - */ -var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile', - '$controller', - function($http, $templateCache, $route, $anchorScroll, $compile, - $controller) { - return { - restrict: 'ECA', - terminal: true, - link: function(scope, element, attr) { - var lastScope, - onloadExp = attr.onload || ''; - - scope.$on('$routeChangeSuccess', update); - update(); - - - function destroyLastScope() { - if (lastScope) { - lastScope.$destroy(); - lastScope = null; - } - } - - function clearContent() { - element.html(''); - destroyLastScope(); - } - - function update() { - var locals = $route.current && $route.current.locals, - template = locals && locals.$template; - - if (template) { - element.html(template); - destroyLastScope(); - - var link = $compile(element.contents()), - current = $route.current, - controller; - - lastScope = current.scope = scope.$new(); - if (current.controller) { - locals.$scope = lastScope; - controller = $controller(current.controller, locals); - element.children().data('$ngControllerController', controller); - } - - link(lastScope); - lastScope.$emit('$viewContentLoaded'); - lastScope.$eval(onloadExp); - - // $anchorScroll might listen on event... - $anchorScroll(); - } else { - clearContent(); - } - } - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:script - * - * @description - * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the - * template can be used by `ngInclude`, `ngView` or directive templates. - * - * @restrict E - * @param {'text/ng-template'} type must be set to `'text/ng-template'` - * - * @example - - - - - Load inlined template -
-
- - it('should load template defined inside script tag', function() { - element('#tpl-link').click(); - expect(element('#tpl-content').text()).toMatch(/Content of the template/); - }); - -
- */ -var scriptDirective = ['$templateCache', function($templateCache) { - return { - restrict: 'E', - terminal: true, - compile: function(element, attr) { - if (attr.type == 'text/ng-template') { - var templateUrl = attr.id, - // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent - text = element[0].text; - - $templateCache.put(templateUrl, text); - } - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:select - * @restrict E - * - * @description - * HTML `SELECT` element with angular data-binding. - * - * # `ngOptions` - * - * Optionally `ngOptions` attribute can be used to dynamically generate a list of `