Welcome to MyEtherWallet, a free, open-source, client-side tool for interacting
+ with the blockchain. MyEtherWallet, Inc. values privacy and we make a
+ concerted effort to minimize and, to the extent possible, eliminate the
+ exposure of personal data during the use of our interface. MyEtherWallet
+ does not collect, hold, or store keys, account information, or passwords.
+ We do not collect data passively, do not monetize the collection of data,
+ and do not use your data for marketing or advertising.
+
+ To the extent we collect any personal information, this privacy policy
+ (“Policy”) describes how MyEtherWallet collects, uses, and shares personal
+ information of people who visit our website (the “Site”), use our mobile
+ application, MEWconnect (the “App”), or otherwise use our services
+ (collectively, the “Services”).
+
+
+ This Policy applies to anyone who accesses the Services. Please read the
+ Policy carefully to understand our practices regarding your information
+ and how we will treat it. By visiting the Site, App, and/or using the
+ Services, you acknowledge that the collection, use, and sharing of your
+ information will take place as described in this Policy.
+
+
+ So that we are clear about the terminology we are using, when we use the
+ phrase “Personal Information” in this Privacy Policy, we mean information
+ about an individual that (either by itself or when combined with information
+ from other available sources) allows that individual to be identified,
+ including, the individual’s name, telephone number, or e-mail address.
+
+
THE BLOCKCHAIN
+
+ Due to the inherent transparency of many blockchains, including the Ethereum
+ Blockchain, transactions that individuals broadcast via MyEtherWallet may
+ be publicly accessible. This includes, but is not limited to, your public
+ sending address, the public address of the receiver, the amount sent or
+ received, and any other data a user has chosen to include in a given
+ transaction. Information stored on a blockchain may be public, immutable,
+ and difficult or even impossible to remove or delete. Transactions and
+ addresses may reveal information about the user’s identity and information
+ can potentially be correlated now or in the future by any party who chooses
+ to do so, including law enforcement. Users are encouraged to review how
+ privacy and transparency on the blockchain works.
+
+
WHAT WE COLLECT
+
+ We collect information about you as described below. We use this
+ information to enhance your experience with our Services.
+
+
Information You Provide
+
+ We may collect Personal Information you choose to provide to us. For
+ example, when you contact us for support through the Services, you give
+ us with your e-mail address and any other information that you choose to
+ provide. Also, if you participate in a MyEtherWallet offer, give-away, or
+ promotion (“Promotion”), you provide your name, e-mail address, and
+ mailing address.
+
+
California Do Not Track Disclosures
+
+ MyEtherWallet does not track users over time and across third party
+ websites to provide targeted advertising and therefore does not respond
+ to Do Not Track (DNT) signals.
+
+
USE OF INFORMATION
+
+ We use the information that we have about you to provide support and certain Services to you.
+
+
+ We may use the Personal Information we collect from and about you to (1)
+ provide you with information or services that you request from us,
+ including to respond to your comments, questions, and/or provide customer
+ service; (2) monitor and analyze usage and trends and personalize and
+ improve the Services and your experience using the Services; and (3)
+ for any other purpose with your consent.
+
+
SHARING OF PERSONAL INFORMATION
+
+ We will not disclose your Personal Information other than as described
+ below, and we do not and will not sell your Personal Information to anyone.
+
+
+ We may share the Personal Information we collect from and about you (1)
+ to fulfill the purpose for which you provided it; (2) with your consent;
+ (3) for legal, protection, and safety purposes; (4) to comply with any
+ court order, law, or legal process, including to respond to any government
+ or regulatory request; (5) to protect the rights of MyEtherWallet, our
+ agents, customers, and others, including by enforcing our agreements,
+ policies, and terms of service; and (6) with those who need it to do work
+ for us (our Service Providers, as defined below).
+
+
Service providers
+
+ We may contract with third parties to perform functions related to the
+ Services (“Service Providers”). In general, Service Providers will have
+ access to your Personal Information only to the extent needed to perform
+ their business functions but may not use or share that personal
+ information for purposes outside the scope of their functions related to
+ the Services.
+
+
LINKS TO OTHER SITES
+
+ The Services contain links to other third-party websites or applications.
+ Once you click on such a link and leave the Site or are redirected to a
+ third-party website or application, you are no longer governed by this
+ Policy. Any information you provide on those sites is subject to that
+ third party’s privacy policy and we are not responsible for the privacy
+ and security practices and policies of those third-party sites or
+ applications.
+
+
OUR COMMITMENT TOWARDS CHILDREN'S PRIVACY
+
+ We do not direct the Services to, nor do we knowingly collect any Personal
+ Information from children under 13. Children under 13 are not eligible to
+ use the Services. If we learn that someone using our Services is under 13
+ years of age, we will take steps to remove any Personal Information from
+ our database and to prevent them from utilizing the Services.
+
+
SECURITY OF YOUR PERSONAL INFORMATION & RIGHTS
+
+ We are committed to protecting the security of Personal Information. We
+ have taken certain physical, administrative, and technical steps to help
+ safeguard the information we collect from and about you. While we take
+ steps to help ensure the integrity and security of our network and
+ systems, we cannot guarantee our security measures.
+
+
In certain circumstances, you will also have the following rights:
+
+
+ Right to access: the right to request certain information about, access
+ to and copies of any Personal Information about you that we are holding
+ (please note that you are entitled to request one copy of the Personal
+ Information that we hold about you at no cost, but for any further copies,
+ we reserve the right to charge a reasonable fee based on administration
+ costs);
+
+
+ Right to rectification: the right to have your Personal Information
+ rectified if it is inaccurate or incomplete;
+
+
+ Right to erasure/“right to be forgotten”: where the processing of your
+ information is based on your consent, the right to withdraw that consent
+ and the right to request that we delete or erase your Personal
+ Information from our systems (however, this will not apply if we are
+ required to hold on to the information for compliance with any legal
+ obligation, or if we require the information to establish or defend any
+ legal claim);
+
+
+ Right to restriction of use of your information: the right to stop us
+ from using your Personal Information or limit the way in which we can
+ use it;
+
+
+ Right to data portability: the right to request that we return any
+ information you have provided in a structured, commonly used, and
+ machine-readable format, or that we send it directly to another company,
+ where technically feasible; and
+
+
+ Right to object: the right to object to our use of your Personal
+ Information including where we use it for our legitimate interests.
+
The following legal bases apply to the ways in which we use and share an individual’s Personal Information:
+
+
+ We rely on an individual’s consent to process Personal Information to
+ provide support and/or carry out Promotions. This consent can be
+ withdrawn at any time.
+
+
+ We also process the information provided by an individual in our
+ legitimate interests in ensuring our business is conducted legitimately
+ and to a high standard.
+
+
+
RETENTION
+
+ We will retain the information you provide in order to process your
+ request, provide support, and/or carry out and fulfill our Promotions. If
+ you request support, we will retain your information for no longer than
+ six (6) months. If you participate in a Promotion, we will retain your
+ information until the Promotion is carried out and ninety (90) days after
+ any prize, reward, or offer is fulfilled. Your Personal Information will
+ then be deleted.
+
+
CONTACT INFORMATION
+
+ We welcome your comments or questions about this Policy. You may contact us at privacy@myetherwallet.com
+
+
CHANGES TO PRIVACY POLICY
+
+ We may modify this Policy from time to time. If we make any changes, we
+ will change the Last Updated date above. We also may provide additional
+ notice, as applicable, depending on the type of change. If you object to
+ any changes, you may stop using the Services. Your continued use of the
+ Services after we publish or otherwise provide notice about our changes
+ to the Policy means that you are consenting to the updated Policy.
+
+ You may know this as your "Account #" or your "Public Key". It's what you send people so they can send you ETH. That icon is an easy way to recognize your address.
+
+
+ Your Address:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This Keystore / JSON file matches the format used by Mist & Geth so you can easily import it in the future. It is the recommended file to download and back up.
+
+ This is the unencrypted text version of your private key, meaning no password is necessary. If someone were to find your unencrypted private key, they could access your wallet without a password. For this reason, encrypted versions are typically recommended.
+
+
+
+ Private Key (unencrypted)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ProTip: If you cannot print this right now, click "Print" and save it as a PDF until you are able to get it printed. Remove it from your computer afterwards!
+
Always backup your keys: MyEtherWallet.com & MyEtherWallet CX are not "web wallets". You do not create an account or give us your funds to hold onto. No data leaves your computer / your browser. We make it easy for you to create, save, and access your information and interact with the blockchain.
+
+
We are not responsible for any loss: Ethereum, MyEtherWallet.com & MyEtherWallet CX, and some of the underlying Javascript libraries we use are under active development. While we have thoroughly tested & tens of thousands of wallets have been successfully created by people all over the globe, there is always the possibility something unexpected happens that causes your funds to be lost. Please do not invest more than you are willing to lose, and please be careful.
+
+
Translations of MyEtherWallet: The community has done an amazing job translating MyEtherWallet into a variety of languages. However, MyEtherWallet can only verify the validity and accuracy of the information provided in English and, because of this, the English version of our website is the official text.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ It looks like you didn't finish reading through these slides last time. ProTip: Finish reading through the slides 😉
+
+
+
+
+
+ Welcome to MyEtherWallet.com
+
+
+
+ We know this click-through shit is annoying. We are sorry.
+
+
+
+
+
+
+ Please take some time to understand this for your own safety. 🙏
+
+
+ Your funds will be stolen if you do not head these warnings.
+
+
+
+ We cannot recover your funds or freeze your account if you visit a phishing site or lose your private key.
+
+
+ What is MEW?
+
+
+
+ MyEtherWallet is a free, open-source, client-side interface.
+
+
+ We allow you to interact directly with the blockchain while remaining in full control of your keys & your funds.
+
+
+ **You** and **only you** are responsible for your security.
+
+ When you open an account with a bank or exchange, they create an account for you in their system.
+
+
+ They keep track of your personal information, account passwords, balances, transactions and ultimately your money.
+
+
+ They charge fees to manage your account and provide services, like refunding transactions when your card gets stolen.
+
+
+ You can write a check or charge your debit card to send money, go online to check your balance, reset your password, and get a new debit card if you lose it.
+
+
+ You have an account *with the bank* and they decide how much money you can send, where you can send it, and how long to hold on a suspicious deposit. All for a fee.
+
+ The blockchain is like a huge, global, decentralized spreadsheet.
+
+
+ It keeps track of who sent how many coins to whom, and what the balance of every account is.
+
+
+ It is stored and maintained by thousands of people (miners) across the globe who have special computers.
+
+
+ It is made up of all the individual transactions sent from MyEtherWallet, MetaMask, Exodus, Mist, Geth, Parity, and everywhere else.
+
+
+ When you see your balance on MyEtherWallet.com or view your transactions on [etherscan.io](https://etherscan.io), you are seeing data on the blockchain, not in our personal systems.
+
+ Because we need you to understand that we **cannot**...
+
+
+
+ Access your account or send your funds for you.
+
+
+ Recover or change your private key.
+
+
+ Recover or reset your password.
+
+
+ Reverse, cancel, or refund transactions.
+
+
+ Freeze accounts.
+
+
+
+ **You** and **only you** are responsible for your security.
+
+
+
+ Be diligent to keep your private key and password safe. Your private key is sometimes called your mnemonic phrase, keystore file, UTC file, JSON file, wallet file.
+
+
+ If lose your private key or password, no one can recover it.
+
+
+ If you enter your private key on a phishing website, you will have **all your funds taken**.
+
+ If MyEtherWallet can't do those things, what's the point?
+
+
+
+
+
+
+
+
+ Because that is the point of decentralization and the blockchain.
+
+
+ You don't have to rely on your bank, government, or anyone else when you want to move your funds.
+
+
+ You don't have to rely on the security of an exchange or bank to keep your funds safe.
+
+
+ If you don't find these things valuable, ask yourself why you think the blockchain and cryptocurrencies are valuable. 😉
+
+
+ If you don't like the sound of this, consider using [Coinbase](https://www.coinbase.com/) or [Blockchain.info](https://blockchain.info/wallet/#/signup). They have more familiar accounts with usernames & passwords.
+
+
+ If you are scared but want to use MEW, [get a hardware wallet](https://myetherwallet.github.io/knowledge-base/hardware-wallets/hardware-wallet-recommendations.html)! These keep your keys secure.
+
+ Phishers send you a message with a link to a website that looks just like MyEtherWallet, EtherDelta, Paypal, or your bank, but is not the real website. They steal your information and then steal your money.
+
+
+
+
+
+ Install [EAL](https://chrome.google.com/webstore/detail/etheraddresslookup/pdknmigbbbhmllnmgdfalmedcmcefdfn) or [MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn) or [Cryptonite by Metacert](https://chrome.google.com/webstore/detail/cryptonite-by-metacert/keghdcpemohlojlglbiegihkljkgnige) or the [MyEtherWallet Chrome Extension](https://chrome.google.com/webstore/detail/myetherwallet-cx/nlbmnnijcnlegkjjpcfjclmcfggfefdm) to block malicious websites.
+
+
+ Always check the URL: `https://www.myetherwallet.com`.
+
+
+ Always make sure the URL bar has `MYETHERWALLET Inc` in green.
+
+
+ Do not trust messages or links sent to you randomly via email, Slack, Reddit, Twitter, etc.
+
+
+ Always navigate directly to a site before you enter information. Do not enter information after clicking a link from a message or email.
+
+
+ [Install an AdBlocker](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en) and do not click ads on your search engine (e.g. Google).
+
+ People will try to get you to give them money in return for nothing.
+
+
+
+
+
+
+ If it is too good to be true, it probably is.
+
+
+ Research before sending money to someone or some project. Look for information on a variety of websites and forums. Be wary.
+
+
+ Ask questions when you don't understand something or it doesn't seem right.
+
+
+ Don't let fear, FUD, or FOMO win over common sense. If something is very urgent, ask yourself 'why?'. It may be to create FOMO or prevent you from doing research.
+
+ If you lose your private key or password, it is gone forever. Don't lose it.
+
+
+
+
+
+ Make a backup of your private key and password. Do NOT just store it on your computer. Print it out on a piece of paper or save it to a USB drive.
+
+
+ Store this paper or USB drive in a different physical location. A backup is not useful if it is destroyed by a fire or flood along with your laptop.
+
+
+ Do not store your private key in Dropbox, Google Drive, or other cloud storage. If that account is compromised, your funds will be stolen.
+
+
+ If you have more than 1-week's worth of pay worth of cryptocurrency, get a hardware wallet. No excuses. It's worth it. I promise.
+
+
+
+
+
+
+
+
+
+ [Even more Security Tips!](https://myetherwallet.github.io/knowledge-base/getting-started/protecting-yourself-and-your-funds.html)
+
\n \n This is a recommended way to access your wallet.\n
\n
\n MetaMask is a browser extension that allows you to access your wallet quickly, safely & easily. It is more secure because you never enter your private key on a website. It protects you from phishing & malicious websites.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n Please use MyEtherWallet on a secure (SSL / HTTPS) connection to connect.\n
\n
\n \n Open the Ethereum application (or a contract application)\n \n \n Open the Expanse application (or a contract application)\n \n \n Open the Ubiq application (or a contract application)\n \n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website is dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n \n This is a recommended way to access your wallet.\n
\n
\n MetaMask is a browser extension that allows you to access your wallet quickly, safely & easily. It is more secure because you never enter your private key on a website. It protects you from phishing & malicious websites.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n Please use MyEtherWallet on a secure (SSL / HTTPS) connection to connect.\n
\n
\n \n Open the Ethereum application (or a contract application)\n \n \n Open the Expanse application (or a contract application)\n \n \n Open the Ubiq application (or a contract application)\n \n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is a recommended way to access your wallet.\n
\n
\n A hardware wallet is a small USB device that allows you to access your wallet quickly, safely & easily. It is more secure because your private key never leaves the hardware wallet. It protects you from phishing, malware, and more.\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n \n This is not a recommended way to access your wallet.\n
\n
\n Entering your private key on a website is dangerous. If our website is compromised or you accidentally visit a different website, your funds will be stolen. Please consider:\n
\n\n \n\n \n\n \n\n\n";
},{}],58:[function(require,module,exports){
'use strict';
@@ -10750,7 +10757,7 @@ ens.prototype.checkDomain = function () {
module.exports = ens;
}).call(this,require("buffer").Buffer)
-},{"./ensConfigs/ETHConfig.json":62,"./ensConfigs/ROPConfig.json":63,"./ensConfigs/RinkebyConfig.json":64,"./ensConfigs/auctionABI.json":65,"./ensConfigs/deedABI.json":66,"./ensConfigs/registryABI.json":67,"./ensConfigs/resolverABI.json":68,"./ensConfigs/subDomainABI.json":69,"buffer":239,"idna-uts46":625}],62:[function(require,module,exports){
+},{"./ensConfigs/ETHConfig.json":62,"./ensConfigs/ROPConfig.json":63,"./ensConfigs/RinkebyConfig.json":64,"./ensConfigs/auctionABI.json":65,"./ensConfigs/deedABI.json":66,"./ensConfigs/registryABI.json":67,"./ensConfigs/resolverABI.json":68,"./ensConfigs/subDomainABI.json":69,"buffer":244,"idna-uts46":629}],62:[function(require,module,exports){
module.exports={
"public": {
"resolver": "0x1da022710dF5002339274AaDEe8D58218e9D6AB5",
@@ -15773,7 +15780,7 @@ if (IS_CX) {
app.controller('cxDecryptWalletCtrl', ['$scope', '$sce', 'walletService', cxDecryptWalletCtrl]);
}
-},{"./ajaxReq":22,"./bity":23,"./constants/darkListConst":24,"./controllers/CX/addWalletCtrl":25,"./controllers/CX/cxDecryptWalletCtrl":26,"./controllers/CX/mainPopCtrl":27,"./controllers/CX/myWalletsCtrl":28,"./controllers/CX/quickSendCtrl":29,"./controllers/bulkGenCtrl":30,"./controllers/contractsCtrl":31,"./controllers/decryptWalletCtrl":32,"./controllers/domainsaleCtrl":33,"./controllers/ensCtrl":34,"./controllers/footerCtrl":35,"./controllers/helpersCtrl":36,"./controllers/offlineTxCtrl":37,"./controllers/onboardingCtrl":38,"./controllers/sendTxCtrl":39,"./controllers/signMsgCtrl":40,"./controllers/swapCtrl":41,"./controllers/tabsCtrl":42,"./controllers/txStatusCtrl":43,"./controllers/viewCtrl":44,"./controllers/viewWalletCtrl":45,"./controllers/walletBalanceCtrl":46,"./controllers/walletGenCtrl":47,"./customGas.js":48,"./cxFuncs":49,"./directives/QRCodeDrtv":50,"./directives/addressFieldDrtv":51,"./directives/balanceDrtv":53,"./directives/blockiesDrtv":54,"./directives/cxWalletDecryptDrtv":55,"./directives/fileReaderDrtv":56,"./directives/walletDecryptDrtv":58,"./domainsale":59,"./ens":61,"./ethFuncs":70,"./etherUnits":71,"./globalFuncs":72,"./homoglyphs.json":73,"./kyber":74,"./localStoragePolyfill":82,"./myetherwallet":84,"./nodes":92,"./services/globalService":93,"./services/walletService":94,"./solidity/coder":98,"./solidity/utils":109,"./staticJS/customMarked":110,"./staticJS/digitalBitboxEth":111,"./staticJS/digitalBitboxUsb":112,"./staticJS/ledger-eth":113,"./staticJS/ledger3":114,"./staticJS/secalotEth":115,"./staticJS/secalotUsb":116,"./staticJS/trezorConnect":117,"./staticJS/u2f-api":118,"./tokenlib":119,"./translations/translate.js":162,"./uiFuncs":166,"./validator":167,"./web3Wallet":168,"angular":176,"angular-animate":170,"angular-sanitize":172,"angular-translate":174,"angular-translate-handler-log":173,"babel-polyfill":192,"bignumber.js":195,"bip39":196,"crypto":573,"detect-browser":580,"ethereumjs-tx":604,"ethereumjs-util":605,"hdkey":622,"levenshtein":640,"punycode":236,"scryptsy":683,"similarity":698,"string-format":700,"unicode/category/Ll":703,"uuid":710,"wallet-address-validator":719,"xss-filters":720}],84:[function(require,module,exports){
+},{"./ajaxReq":22,"./bity":23,"./constants/darkListConst":24,"./controllers/CX/addWalletCtrl":25,"./controllers/CX/cxDecryptWalletCtrl":26,"./controllers/CX/mainPopCtrl":27,"./controllers/CX/myWalletsCtrl":28,"./controllers/CX/quickSendCtrl":29,"./controllers/bulkGenCtrl":30,"./controllers/contractsCtrl":31,"./controllers/decryptWalletCtrl":32,"./controllers/domainsaleCtrl":33,"./controllers/ensCtrl":34,"./controllers/footerCtrl":35,"./controllers/helpersCtrl":36,"./controllers/offlineTxCtrl":37,"./controllers/onboardingCtrl":38,"./controllers/sendTxCtrl":39,"./controllers/signMsgCtrl":40,"./controllers/swapCtrl":41,"./controllers/tabsCtrl":42,"./controllers/txStatusCtrl":43,"./controllers/viewCtrl":44,"./controllers/viewWalletCtrl":45,"./controllers/walletBalanceCtrl":46,"./controllers/walletGenCtrl":47,"./customGas.js":48,"./cxFuncs":49,"./directives/QRCodeDrtv":50,"./directives/addressFieldDrtv":51,"./directives/balanceDrtv":53,"./directives/blockiesDrtv":54,"./directives/cxWalletDecryptDrtv":55,"./directives/fileReaderDrtv":56,"./directives/walletDecryptDrtv":58,"./domainsale":59,"./ens":61,"./ethFuncs":70,"./etherUnits":71,"./globalFuncs":72,"./homoglyphs.json":73,"./kyber":74,"./localStoragePolyfill":82,"./myetherwallet":84,"./nodes":92,"./services/globalService":93,"./services/walletService":94,"./solidity/coder":98,"./solidity/utils":109,"./staticJS/customMarked":110,"./staticJS/digitalBitboxEth":111,"./staticJS/digitalBitboxUsb":112,"./staticJS/ledger-eth":113,"./staticJS/ledger3":114,"./staticJS/secalotEth":115,"./staticJS/secalotUsb":116,"./staticJS/trezorConnect":117,"./staticJS/u2f-api":118,"./tokenlib":119,"./translations/translate.js":162,"./uiFuncs":166,"./validator":167,"./web3Wallet":168,"angular":176,"angular-animate":170,"angular-sanitize":172,"angular-translate":174,"angular-translate-handler-log":173,"babel-polyfill":195,"bignumber.js":199,"bip39":200,"crypto":577,"detect-browser":584,"ethereumjs-tx":608,"ethereumjs-util":609,"hdkey":626,"levenshtein":644,"punycode":240,"scryptsy":686,"similarity":701,"string-format":703,"unicode/category/Ll":707,"uuid":711,"wallet-address-validator":724,"xss-filters":725}],84:[function(require,module,exports){
(function (Buffer){
'use strict';
@@ -16180,7 +16187,7 @@ Wallet.getWalletFromPrivKeyFile = function (strjson, password) {
module.exports = Wallet;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],85:[function(require,module,exports){
+},{"buffer":244}],85:[function(require,module,exports){
'use strict';
var customNode = function customNode(srvrUrl, port, httpBasicAuthentication) {
@@ -16572,7 +16579,7 @@ nodes.nodeTypes = {
MUSIC: "MUSIC",
GO: "GO",
EOSC: "EOSC",
- AKROMA: "AKROMA",
+ AKA: "AKA",
ESN: "ESN",
PIRL: "PIRL",
ETHO: "ETHO",
@@ -16816,16 +16823,16 @@ nodes.nodeList = {
},
tomo: {
name: "TOMO",
- blockExplorerTX: "https://explorer.tomocoin.io/#/tx/[[txHash]]",
- blockExplorerAddr: "https://explorer.tomocoin.io/#/address/[[address]]",
+ blockExplorerTX: "https://scan.testnet.tomochain.com/txs/[[txHash]]",
+ blockExplorerAddr: "https://scan.testnet.tomochain.com/address/[[address]]",
type: nodes.nodeTypes.TOMO,
eip155: true,
- chainId: 40686,
+ chainId: 89,
tokenList: require("./tokens/tomoTokens.json"),
abiList: require("./abiDefinitions/tomoAbi.json"),
estimateGas: true,
- service: "core.tomocoin.io",
- lib: new nodes.customNode("https://core.tomocoin.io", "")
+ service: "testnet.tomochain.com",
+ lib: new nodes.customNode("https://testnet.tomochain.com", "")
},
ella: {
name: "ELLA",
@@ -16914,14 +16921,14 @@ nodes.nodeList = {
tokenList: require("./tokens/eoscTokens.json"),
abiList: require("./abiDefinitions/eoscAbi.json"),
estimateGas: true,
- service: "eos-classic.io",
+ service: "EOS Classic",
lib: new nodes.customNode("https://node.eos-classic.io", "")
},
aka_remote: {
name: "AKA",
blockExplorerTX: "https://akroma.io/explorer/transaction/[[txHash]]",
blockExplorerAddr: "https://akroma.io/explorer/address/[[address]]",
- type: nodes.nodeTypes.AKROMA,
+ type: nodes.nodeTypes.AKA,
eip155: true,
chainId: 200625,
tokenList: require("./tokens/akromaTokens.json"),
@@ -16934,7 +16941,7 @@ nodes.nodeList = {
name: "AKA",
blockExplorerTX: "https://akroma.io/explorer/transaction/[[txHash]]",
blockExplorerAddr: "https://akroma.io/explorer/address/[[address]]",
- type: nodes.nodeTypes.AKROMA,
+ type: nodes.nodeTypes.AKA,
eip155: true,
chainId: 200625,
tokenList: require("./tokens/akromaTokens.json"),
@@ -17527,7 +17534,7 @@ module.exports = {
defaultAccount: undefined
};
-},{"bignumber.js":195}],100:[function(require,module,exports){
+},{"bignumber.js":199}],100:[function(require,module,exports){
'use strict';
var f = require('./formatters');
@@ -17806,7 +17813,7 @@ module.exports = {
formatOutputAddress: formatOutputAddress
};
-},{"./config":99,"./param":103,"./utils":109,"bignumber.js":195}],102:[function(require,module,exports){
+},{"./config":99,"./param":103,"./utils":109,"bignumber.js":199}],102:[function(require,module,exports){
'use strict';
var f = require('./formatters');
@@ -18970,7 +18977,7 @@ module.exports = {
isJson: isJson
};
-},{"bignumber.js":195,"ethereumjs-util":605,"utf8":705}],110:[function(require,module,exports){
+},{"bignumber.js":199,"ethereumjs-util":609,"utf8":709}],110:[function(require,module,exports){
'use strict';
var marked = require('marked');
@@ -19001,7 +19008,7 @@ marked.setOptions({
});
module.exports = marked;
-},{"marked":641}],111:[function(require,module,exports){
+},{"marked":645}],111:[function(require,module,exports){
(function (Buffer){
/**
* (c) 2017 Douglas Bakkum, Shift Devices AG
@@ -19169,7 +19176,7 @@ DigitalBitboxEth.prototype.signMessage = function (path, messageHex, callback) {
module.exports = DigitalBitboxEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":239,"crypto":573,"hdkey":622}],112:[function(require,module,exports){
+},{"buffer":244,"crypto":577,"hdkey":626}],112:[function(require,module,exports){
(function (Buffer){
/**
* (c) 2017 Douglas Bakkum, Shift Devices AG
@@ -19223,7 +19230,7 @@ DigitalBitboxUsb.prototype.exchange = function (msg, callback) {
module.exports = DigitalBitboxUsb;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],113:[function(require,module,exports){
+},{"buffer":244}],113:[function(require,module,exports){
(function (Buffer){
/********************************************************************************
* Ledger Communication toolkit
@@ -19438,7 +19445,7 @@ LedgerEth.prototype.signPersonalMessage_async = function (path, messageHex, call
module.exports = LedgerEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],114:[function(require,module,exports){
+},{"buffer":244}],114:[function(require,module,exports){
(function (Buffer){
/********************************************************************************
* Ledger Communication toolkit
@@ -19509,7 +19516,7 @@ Ledger3.prototype.exchange = function (apduHex, callback) {
module.exports = Ledger3;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],115:[function(require,module,exports){
+},{"buffer":244}],115:[function(require,module,exports){
(function (Buffer){
'use strict';
@@ -19768,7 +19775,7 @@ SecalotEth.prototype.signMessage = function (path, message, callback) {
module.exports = SecalotEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],116:[function(require,module,exports){
+},{"buffer":244}],116:[function(require,module,exports){
(function (Buffer){
'use strict';
@@ -19812,7 +19819,7 @@ SecalotUsb.prototype.exchange = function (apduHex, callback) {
module.exports = SecalotUsb;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],117:[function(require,module,exports){
+},{"buffer":244}],117:[function(require,module,exports){
'use strict';
/**
@@ -21564,8 +21571,16 @@ module.exports=[
]
},{}],125:[function(require,module,exports){
-arguments[4][2][0].apply(exports,arguments)
-},{"dup":2}],126:[function(require,module,exports){
+module.exports=[
+ {
+ "address": "0x92b5120545f457cd0ffcfd787d17a5d777a54293",
+ "symbol": "EOSG",
+ "decimal": 0,
+ "type": "default"
+ }
+]
+
+},{}],126:[function(require,module,exports){
module.exports=[
{
"address": "0x72ea3508d9d817a91465abb59be10fef9857a055",
@@ -21680,7 +21695,7 @@ module.exports=[
{
"address": "0xBa7DCBa2Ade319Bc772DB4df75A76BA00dFb31b0",
"symbol": "A18",
- "decimal": 0,
+ "decimal": 18,
"type": "default"
},
{
@@ -22332,7 +22347,7 @@ module.exports=[
"type": "default"
},
{
- "address": "0xB07ec2c28834B889b1CE527Ca0F19364cD38935c",
+ "address": "0x954b890704693af242613edef1b603825afcd708",
"symbol": "CARD",
"decimal": 18,
"type": "default"
@@ -23033,6 +23048,12 @@ module.exports=[
"decimal": 2,
"type": "default"
},
+ {
+ "address": "0x8869b1f9bc8b246a4d7220f834e56ddfdd8255e7",
+ "symbol": "ECP",
+ "decimal": 18,
+ "type": "default"
+ },
{
"address": "0xfa1de2ee97e4c10c94c91cb2b5062b89fb140b82",
"symbol": "EDC",
@@ -24611,6 +24632,12 @@ module.exports=[
"decimal": 8,
"type": "default"
},
+ {
+ "address": "0x0db03B6CDe0B2d427C64a04FeAfd825938368f1F",
+ "symbol": "PDATA",
+ "decimal": 18,
+ "type": "default"
+ },
{
"address": "0x8Ae56a6850a7cbeaC3c3Ab2cB311e7620167eAC8",
"symbol": "PEG",
@@ -24983,6 +25010,12 @@ module.exports=[
"decimal": 18,
"type": "default"
},
+ {
+ "address": "0xC16b542ff490e01fcc0DC58a60e1EFdc3e357cA6",
+ "symbol": "ROCK2",
+ "decimal": 0,
+ "type": "default"
+ },
{
"address": "0xc9de4b7f0c3d991e967158e4d4bfa4b51ec0b114",
"symbol": "ROK",
@@ -25007,6 +25040,12 @@ module.exports=[
"decimal": 18,
"type": "default"
},
+ {
+ "address": "0xdEE02D94be4929d26f67B64Ada7aCf1914007F10",
+ "symbol": "RUNE",
+ "decimal": 18,
+ "type": "default"
+ },
{
"address": "0x3d1ba9be9f66b8ee101911bc36d3fb562eac2244",
"symbol": "RVT",
@@ -26050,8 +26089,16 @@ module.exports=[{
}]
},{}],139:[function(require,module,exports){
-arguments[4][1][0].apply(exports,arguments)
-},{"dup":1}],140:[function(require,module,exports){
+module.exports=[
+ {
+ "address": "0x8b353021189375591723e7384262f45709a3c3dc",
+ "symbol": "TOMO",
+ "decimal": 18,
+ "type": "default"
+ }
+]
+
+},{}],140:[function(require,module,exports){
module.exports=[
{
"address":"0xd245207cfbf6eb6f34970db2a807ab1d178fde6c",
@@ -30493,7 +30540,7 @@ uiFuncs.notifier = {
module.exports = uiFuncs;
}).call(this,require("buffer").Buffer)
-},{"buffer":239}],167:[function(require,module,exports){
+},{"buffer":244}],167:[function(require,module,exports){
'use strict';
var validator = function validator() {};
@@ -30634,8 +30681,8 @@ module.exports = Web3Wallet;
'use strict';
/**
- * @license AngularJS v1.6.8
- * (c) 2010-2017 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.7.3
+ * (c) 2010-2018 Google, Inc. http://angularjs.org
* License: MIT
*/
(function (window, angular) {
@@ -30941,7 +30988,7 @@ module.exports = Web3Wallet;
return element instanceof jqLite ? element[0] : element;
}
- function applyGeneratedPreparationClasses(element, event, options) {
+ function applyGeneratedPreparationClasses($$jqLite, element, event, options) {
var classes = '';
if (event) {
classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
@@ -31168,7 +31215,7 @@ module.exports = Web3Wallet;
* Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
* is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
* any automatic control over cancelling animations and/or preventing animations from being run on
- * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to
+ * child elements will not be handled by AngularJS. For this to work as expected, please use `$animate` to
* trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
* the CSS animation.
*
@@ -31450,33 +31497,6 @@ module.exports = Web3Wallet;
return [style, value];
}
- function createLocalCacheLookup() {
- var cache = Object.create(null);
- return {
- flush: function flush() {
- cache = Object.create(null);
- },
-
- count: function count(key) {
- var entry = cache[key];
- return entry ? entry.total : 0;
- },
-
- get: function get(key) {
- var entry = cache[key];
- return entry && entry.value;
- },
-
- put: function put(key, value) {
- if (!cache[key]) {
- cache[key] = { total: 1, value: value };
- } else {
- cache[key].total++;
- }
- }
- };
- }
-
// we do not reassign an already present style value since
// if we detect the style property value again we may be
// detecting styles that were added via the `from` styles.
@@ -31493,23 +31513,13 @@ module.exports = Web3Wallet;
}
var $AnimateCssProvider = ['$animateProvider', /** @this */function ($animateProvider) {
- var gcsLookup = createLocalCacheLookup();
- var gcsStaggerLookup = createLocalCacheLookup();
- this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue', function ($window, $$jqLite, $$AnimateRunner, $timeout, $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
+ this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$animateCache', '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue', function ($window, $$jqLite, $$AnimateRunner, $timeout, $$animateCache, $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
- var parentCounter = 0;
- function gcsHashFn(node, extraClasses) {
- var KEY = '$$ngAnimateParentKey';
- var parentNode = node.parentNode;
- var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
- return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
- }
-
- function computeCachedCssStyles(node, className, cacheKey, properties) {
- var timings = gcsLookup.get(cacheKey);
+ function computeCachedCssStyles(node, className, cacheKey, allowNoDuration, properties) {
+ var timings = $$animateCache.get(cacheKey);
if (!timings) {
timings = computeCssStyles($window, node, properties);
@@ -31518,20 +31528,26 @@ module.exports = Web3Wallet;
}
}
+ // if a css animation has no duration we
+ // should mark that so that repeated addClass/removeClass calls are skipped
+ var hasDuration = allowNoDuration || timings.transitionDuration > 0 || timings.animationDuration > 0;
+
// we keep putting this in multiple times even though the value and the cacheKey are the same
// because we're keeping an internal tally of how many duplicate animations are detected.
- gcsLookup.put(cacheKey, timings);
+ $$animateCache.put(cacheKey, timings, hasDuration);
+
return timings;
}
function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
var stagger;
+ var staggerCacheKey = 'stagger-' + cacheKey;
// if we have one or more existing matches of matching elements
// containing the same parent + CSS styles (which is how cacheKey works)
// then staggering is possible
- if (gcsLookup.count(cacheKey) > 0) {
- stagger = gcsStaggerLookup.get(cacheKey);
+ if ($$animateCache.count(cacheKey) > 0) {
+ stagger = $$animateCache.get(staggerCacheKey);
if (!stagger) {
var staggerClassName = pendClasses(className, '-stagger');
@@ -31546,7 +31562,7 @@ module.exports = Web3Wallet;
$$jqLite.removeClass(node, staggerClassName);
- gcsStaggerLookup.put(cacheKey, stagger);
+ $$animateCache.put(staggerCacheKey, stagger, true);
}
}
@@ -31557,8 +31573,7 @@ module.exports = Web3Wallet;
function waitUntilQuiet(callback) {
rafWaitQueue.push(callback);
$$rAFScheduler.waitUntilQuiet(function () {
- gcsLookup.flush();
- gcsStaggerLookup.flush();
+ $$animateCache.flush();
// DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
// PLEASE EXAMINE THE `$$forceReflow` service to understand why.
@@ -31573,8 +31588,8 @@ module.exports = Web3Wallet;
});
}
- function computeTimings(node, className, cacheKey) {
- var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
+ function computeTimings(node, className, cacheKey, allowNoDuration) {
+ var timings = computeCachedCssStyles(node, className, cacheKey, allowNoDuration, DETECT_CSS_PROPERTIES);
var aD = timings.animationDelay;
var tD = timings.transitionDelay;
timings.maxDelay = aD && tD ? Math.max(aD, tD) : aD || tD;
@@ -31653,7 +31668,6 @@ module.exports = Web3Wallet;
var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
var fullClassName = classes + ' ' + preparationClasses;
- var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
@@ -31664,7 +31678,13 @@ module.exports = Web3Wallet;
return closeAndReturnNoopAnimator();
}
- var cacheKey, stagger;
+ var stagger,
+ cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
+ if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
+ preparationClasses = null;
+ return closeAndReturnNoopAnimator();
+ }
+
if (options.stagger > 0) {
var staggerVal = parseFloat(options.stagger);
stagger = {
@@ -31674,7 +31694,6 @@ module.exports = Web3Wallet;
animationDuration: 0
};
} else {
- cacheKey = gcsHashFn(node, fullClassName);
stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
}
@@ -31705,7 +31724,7 @@ module.exports = Web3Wallet;
temporaryStyles.push(keyframeStyle);
}
- var itemIndex = stagger ? options.staggerIndex >= 0 ? options.staggerIndex : gcsLookup.count(cacheKey) : 0;
+ var itemIndex = stagger ? options.staggerIndex >= 0 ? options.staggerIndex : $$animateCache.count(cacheKey) : 0;
var isFirst = itemIndex === 0;
@@ -31719,7 +31738,7 @@ module.exports = Web3Wallet;
blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
}
- var timings = computeTimings(node, fullClassName, cacheKey);
+ var timings = computeTimings(node, fullClassName, cacheKey, !isStructural);
var relativeDelay = timings.maxDelay;
maxDelay = Math.max(relativeDelay, 0);
maxDuration = timings.maxDuration;
@@ -31755,6 +31774,8 @@ module.exports = Web3Wallet;
return closeAndReturnNoopAnimator();
}
+ var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
+
if (options.delay != null) {
var delayStyle;
if (typeof options.delay !== 'boolean') {
@@ -31840,10 +31861,13 @@ module.exports = Web3Wallet;
animationClosed = true;
animationPaused = false;
- if (!options.$$skipPreparationClasses) {
+ if (preparationClasses && !options.$$skipPreparationClasses) {
$$jqLite.removeClass(element, preparationClasses);
}
- $$jqLite.removeClass(element, activeClasses);
+
+ if (activeClasses) {
+ $$jqLite.removeClass(element, activeClasses);
+ }
blockKeyframeAnimations(node, false);
blockTransitions(node, false);
@@ -32022,9 +32046,9 @@ module.exports = Web3Wallet;
if (flags.recalculateTimingStyles) {
fullClassName = node.getAttribute('class') + ' ' + preparationClasses;
- cacheKey = gcsHashFn(node, fullClassName);
+ cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
- timings = computeTimings(node, fullClassName, cacheKey);
+ timings = computeTimings(node, fullClassName, cacheKey, false);
relativeDelay = timings.maxDelay;
maxDelay = Math.max(relativeDelay, 0);
maxDuration = timings.maxDuration;
@@ -32754,6 +32778,15 @@ module.exports = Web3Wallet;
join: []
};
+ function getEventData(options) {
+ return {
+ addClass: options.addClass,
+ removeClass: options.removeClass,
+ from: options.from,
+ to: options.to
+ };
+ }
+
function makeTruthyCssClassMap(classString) {
if (!classString) {
return null;
@@ -32847,6 +32880,10 @@ module.exports = Web3Wallet;
var disabledElementsLookup = new $$Map();
var animationsEnabled = null;
+ function removeFromDisabledElementsLookup(evt) {
+ disabledElementsLookup.delete(evt.target);
+ }
+
function postDigestTaskFactory() {
var postDigestCalled = false;
return function (fn) {
@@ -33028,6 +33065,11 @@ module.exports = Web3Wallet;
bool = !disabledElementsLookup.get(node);
} else {
// (element, bool) - Element setter
+ if (!disabledElementsLookup.has(node)) {
+ // The element is added to the map for the first time.
+ // Create a listener to remove it on `$destroy` (to avoid memory leak).
+ jqLite(element).on('$destroy', removeFromDisabledElementsLookup);
+ }
disabledElementsLookup.set(node, !bool);
}
}
@@ -33110,9 +33152,9 @@ module.exports = Web3Wallet;
if (skipAnimations) {
// Callbacks should fire even if the document is hidden (regression fix for issue #14120)
- if (documentHidden) notifyProgress(runner, event, 'start');
+ if (documentHidden) notifyProgress(runner, event, 'start', getEventData(options));
close();
- if (documentHidden) notifyProgress(runner, event, 'close');
+ if (documentHidden) notifyProgress(runner, event, 'close', getEventData(options));
return runner;
}
@@ -33169,7 +33211,7 @@ module.exports = Web3Wallet;
if (existingAnimation.state === RUNNING_STATE) {
normalizeAnimationDetails(element, newAnimation);
} else {
- applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
+ applyGeneratedPreparationClasses($$jqLite, element, isStructural ? event : null, options);
event = newAnimation.event = existingAnimation.event;
options = mergeAnimationDetails(element, existingAnimation, newAnimation);
@@ -33268,7 +33310,7 @@ module.exports = Web3Wallet;
// this will update the runner's flow-control events based on
// the `realRunner` object.
runner.setHost(realRunner);
- notifyProgress(runner, event, 'start', {});
+ notifyProgress(runner, event, 'start', getEventData(options));
realRunner.done(function (status) {
close(!status);
@@ -33276,7 +33318,7 @@ module.exports = Web3Wallet;
if (animationDetails && animationDetails.counter === counter) {
clearElementAnimationState(node);
}
- notifyProgress(runner, event, 'close', {});
+ notifyProgress(runner, event, 'close', getEventData(options));
});
});
@@ -33359,7 +33401,7 @@ module.exports = Web3Wallet;
while (parentNode) {
if (!rootNodeDetected) {
- // angular doesn't want to attempt to animate elements outside of the application
+ // AngularJS doesn't want to attempt to animate elements outside of the application
// therefore we need to ensure that the rootElement is an ancestor of the current element
rootNodeDetected = parentNode === rootNode;
}
@@ -33440,6 +33482,62 @@ module.exports = Web3Wallet;
}];
}];
+ /** @this */
+ var $$AnimateCacheProvider = function $$AnimateCacheProvider() {
+
+ var KEY = '$$ngAnimateParentKey';
+ var parentCounter = 0;
+ var cache = Object.create(null);
+
+ this.$get = [function () {
+ return {
+ cacheKey: function cacheKey(node, method, addClass, removeClass) {
+ var parentNode = node.parentNode;
+ var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
+ var parts = [parentID, method, node.getAttribute('class')];
+ if (addClass) {
+ parts.push(addClass);
+ }
+ if (removeClass) {
+ parts.push(removeClass);
+ }
+ return parts.join(' ');
+ },
+
+ containsCachedAnimationWithoutDuration: function containsCachedAnimationWithoutDuration(key) {
+ var entry = cache[key];
+
+ // nothing cached, so go ahead and animate
+ // otherwise it should be a valid animation
+ return entry && !entry.isValid || false;
+ },
+
+ flush: function flush() {
+ cache = Object.create(null);
+ },
+
+ count: function count(key) {
+ var entry = cache[key];
+ return entry ? entry.total : 0;
+ },
+
+ get: function get(key) {
+ var entry = cache[key];
+ return entry && entry.value;
+ },
+
+ put: function put(key, value, isValid) {
+ if (!cache[key]) {
+ cache[key] = { total: 1, value: value, isValid: isValid };
+ } else {
+ cache[key].total++;
+ cache[key].value = value;
+ }
+ }
+ };
+ }];
+ };
+
/* exported $$AnimationProvider */
var $$AnimationProvider = ['$animateProvider', /** @this */function ($animateProvider) {
@@ -33448,6 +33546,7 @@ module.exports = Web3Wallet;
var drivers = this.drivers = [];
var RUNNER_STORAGE_KEY = '$$animationRunner';
+ var PREPARE_CLASSES_KEY = '$$animatePrepareClasses';
function setRunner(element, runner) {
element.data(RUNNER_STORAGE_KEY, runner);
@@ -33461,7 +33560,7 @@ module.exports = Web3Wallet;
return element.data(RUNNER_STORAGE_KEY);
}
- this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler', function ($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler) {
+ this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler', '$$animateCache', function ($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler, $$animateCache) {
var animationQueue = [];
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
@@ -33477,6 +33576,7 @@ module.exports = Web3Wallet;
var animation = animations[i];
lookup.set(animation.domNode, animations[i] = {
domNode: animation.domNode,
+ element: animation.element,
fn: animation.fn,
children: []
});
@@ -33533,7 +33633,7 @@ module.exports = Web3Wallet;
result.push(row);
row = [];
}
- row.push(entry.fn);
+ row.push(entry);
entry.children.forEach(function (childEntry) {
nextLevelEntries++;
queue.push(childEntry);
@@ -33551,6 +33651,8 @@ module.exports = Web3Wallet;
// TODO(matsko): document the signature in a better way
return function (element, event, options) {
+ var node = getDomNode(element);
+
options = prepareAnimationOptions(options);
var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
@@ -33572,8 +33674,6 @@ module.exports = Web3Wallet;
return runner;
}
- setRunner(element, runner);
-
var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
var tempClasses = options.tempClasses;
if (tempClasses) {
@@ -33581,12 +33681,12 @@ module.exports = Web3Wallet;
options.tempClasses = null;
}
- var prepareClassName;
if (isStructural) {
- prepareClassName = 'ng-' + event + PREPARE_CLASS_SUFFIX;
- $$jqLite.addClass(element, prepareClassName);
+ element.data(PREPARE_CLASSES_KEY, 'ng-' + event + PREPARE_CLASS_SUFFIX);
}
+ setRunner(element, runner);
+
animationQueue.push({
// this data is used by the postDigest code and passed into
// the driver step function
@@ -33626,17 +33726,31 @@ module.exports = Web3Wallet;
var toBeSortedAnimations = [];
forEach(groupedAnimations, function (animationEntry) {
+ var element = animationEntry.from ? animationEntry.from.element : animationEntry.element;
+ var extraClasses = options.addClass;
+ extraClasses = (extraClasses ? extraClasses + ' ' : '') + NG_ANIMATE_CLASSNAME;
+ var cacheKey = $$animateCache.cacheKey(node, event, extraClasses, options.removeClass);
+
toBeSortedAnimations.push({
- domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element),
+ element: element,
+ domNode: getDomNode(element),
fn: function triggerAnimationStart() {
+ var startAnimationFn,
+ closeFn = animationEntry.close;
+
+ // in the event that we've cached the animation status for this element
+ // and it's in fact an invalid animation (something that has duration = 0)
+ // then we should skip all the heavy work from here on
+ if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
+ closeFn();
+ return;
+ }
+
// it's important that we apply the `ng-animate` CSS class and the
// temporary classes before we do any driver invoking since these
// CSS classes may be required for proper CSS detection.
animationEntry.beforeStart();
- var startAnimationFn,
- closeFn = animationEntry.close;
-
// in the event that the element was removed before the digest runs or
// during the RAF sequencing then we should not trigger the animation.
var targetElement = animationEntry.anchors ? animationEntry.from.element || animationEntry.to.element : animationEntry.element;
@@ -33664,7 +33778,32 @@ module.exports = Web3Wallet;
// we need to sort each of the animations in order of parent to child
// relationships. This ensures that the child classes are applied at the
// right time.
- $$rAFScheduler(sortAnimations(toBeSortedAnimations));
+ var finalAnimations = sortAnimations(toBeSortedAnimations);
+ for (var i = 0; i < finalAnimations.length; i++) {
+ var innerArray = finalAnimations[i];
+ for (var j = 0; j < innerArray.length; j++) {
+ var entry = innerArray[j];
+ var element = entry.element;
+
+ // the RAFScheduler code only uses functions
+ finalAnimations[i][j] = entry.fn;
+
+ // the first row of elements shouldn't have a prepare-class added to them
+ // since the elements are at the top of the animation hierarchy and they
+ // will be applied without a RAF having to pass...
+ if (i === 0) {
+ element.removeData(PREPARE_CLASSES_KEY);
+ continue;
+ }
+
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
+ if (prepareClassName) {
+ $$jqLite.addClass(element, prepareClassName);
+ }
+ }
+ }
+
+ $$rAFScheduler(finalAnimations);
});
return runner;
@@ -33800,10 +33939,10 @@ module.exports = Web3Wallet;
}
function beforeStart() {
- element.addClass(NG_ANIMATE_CLASSNAME);
- if (tempClasses) {
- $$jqLite.addClass(element, tempClasses);
- }
+ tempClasses = (tempClasses ? tempClasses + ' ' : '') + NG_ANIMATE_CLASSNAME;
+ $$jqLite.addClass(element, tempClasses);
+
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
if (prepareClassName) {
$$jqLite.removeClass(element, prepareClassName);
prepareClassName = null;
@@ -33843,7 +33982,6 @@ module.exports = Web3Wallet;
$$jqLite.removeClass(element, tempClasses);
}
- element.removeClass(NG_ANIMATE_CLASSNAME);
runner.complete(!rejected);
}
};
@@ -33937,7 +34075,7 @@ module.exports = Web3Wallet;
*
*
*/
- var ngAnimateSwapDirective = ['$animate', '$rootScope', function ($animate, $rootScope) {
+ var ngAnimateSwapDirective = ['$animate', function ($animate) {
return {
restrict: 'A',
transclude: 'element',
@@ -33954,10 +34092,10 @@ module.exports = Web3Wallet;
previousScope = null;
}
if (value || value === 0) {
- previousScope = scope.$new();
- $transclude(previousScope, function (element) {
- previousElement = element;
- $animate.enter(element, null, $element);
+ $transclude(function (clone, childScope) {
+ previousElement = clone;
+ previousScope = childScope;
+ $animate.enter(clone, null, $element);
});
}
});
@@ -33971,7 +34109,7 @@ module.exports = Web3Wallet;
* @description
*
* The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
- * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an Angular app.
+ * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an AngularJS app.
*
* ## Usage
* Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
@@ -33982,25 +34120,33 @@ module.exports = Web3Wallet;
* ## Directive Support
* The following directives are "animation aware":
*
- * | Directive | Supported Animations |
- * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
- * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
- * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
- * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
- * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
- * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
- * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
- * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
- * | {@link ng.directive:form#animations form} & {@link ng.directive:ngModel#animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
- * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
- * | {@link module:ngMessages#animations ngMessage} | enter and leave |
- *
- * (More information can be found by visiting each the documentation associated with each directive.)
+ * | Directive | Supported Animations |
+ * |-------------------------------------------------------------------------------|---------------------------------------------------------------------------|
+ * | {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) |
+ * | {@link ngAnimate.directive:ngAnimateSwap#animations ngAnimateSwap} | enter and leave |
+ * | {@link ng.directive:ngClass#animations ngClass / {{class}}} | add and remove |
+ * | {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove |
+ * | {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove |
+ * | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) |
+ * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
+ * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
+ * | {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave |
+ * | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) |
+ * | {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) |
+ * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move |
+ * | {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) |
+ * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
+ * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
+ *
+ * (More information can be found by visiting the documentation associated with each directive.)
+ *
+ * For a full breakdown of the steps involved during each animation event, refer to the
+ * {@link ng.$animate `$animate` API docs}.
*
* ## CSS-based Animations
*
* CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
- * and CSS code we can create an animation that will be picked up by Angular when an underlying directive performs an operation.
+ * and CSS code we can create an animation that will be picked up by AngularJS when an underlying directive performs an operation.
*
* The example below shows how an `enter` animation can be made possible on an element using `ng-if`:
*
@@ -34232,9 +34378,22 @@ module.exports = Web3Wallet;
* .message.ng-enter-prepare {
* opacity: 0;
* }
- *
* ```
*
+ * ### Animating between value changes
+ *
+ * Sometimes you need to animate between different expression states, whose values
+ * don't necessary need to be known or referenced in CSS styles.
+ * Unless possible with another {@link ngAnimate#directive-support "animation aware" directive},
+ * that specific use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as
+ * can be seen in {@link ngAnimate.directive:ngAnimateSwap#examples this example}.
+ *
+ * Note that {@link ngAnimate.directive:ngAnimateSwap} is a *structural directive*, which means it
+ * creates a new instance of the element (including any other/child directives it may have) and
+ * links it to a new scope every time *swap* happens. In some cases this might not be desirable
+ * (e.g. for performance reasons, or when you wish to retain internal state on the original
+ * element instance).
+ *
* ## JavaScript-based Animations
*
* ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
@@ -34259,7 +34418,7 @@ module.exports = Web3Wallet;
* enter: function(element, doneFn) {
* jQuery(element).fadeIn(1000, doneFn);
*
- * // remember to call doneFn so that angular
+ * // remember to call doneFn so that AngularJS
* // knows that the animation has concluded
* },
*
@@ -34307,7 +34466,7 @@ module.exports = Web3Wallet;
*
* ## CSS + JS Animations Together
*
- * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
+ * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of AngularJS,
* defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
* charge of the animation**:
*
@@ -34623,7 +34782,7 @@ module.exports = Web3Wallet;
*
* ## Using $animate in your directive code
*
- * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
+ * So far we've explored how to feed in animations into an AngularJS application, but how do we trigger animations within our own directives in our application?
* By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
* imagine we have a greeting box that shows and hides itself when the data changes
*
@@ -34666,7 +34825,7 @@ module.exports = Web3Wallet;
* });
* ```
*
- * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
+ * (Note that earlier versions of AngularJS prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
* anymore.)
*
* In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
@@ -34681,7 +34840,7 @@ module.exports = Web3Wallet;
* }])
* ```
*
- * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
+ * (Note that you will need to trigger a digest within the callback to get AngularJS to notice any scope-related changes.)
*/
var copy;
@@ -34708,7 +34867,7 @@ module.exports = Web3Wallet;
* Click here {@link ng.$animate to learn more about animations with `$animate`}.
*/
angular.module('ngAnimate', [], function initAngularHelpers() {
- // Access helpers from angular core.
+ // Access helpers from AngularJS core.
// Do it inside a `config` block to ensure `window.angular` is available.
noop = angular.noop;
copy = angular.copy;
@@ -34722,7 +34881,7 @@ module.exports = Web3Wallet;
isDefined = angular.isDefined;
isFunction = angular.isFunction;
isElement = angular.isElement;
- }).info({ angularVersion: '1.6.8' }).directive('ngAnimateSwap', ngAnimateSwapDirective).directive('ngAnimateChildren', $$AnimateChildrenDirective).factory('$$rAFScheduler', $$rAFSchedulerFactory).provider('$$animateQueue', $$AnimateQueueProvider).provider('$$animation', $$AnimationProvider).provider('$animateCss', $AnimateCssProvider).provider('$$animateCssDriver', $$AnimateCssDriverProvider).provider('$$animateJs', $$AnimateJsProvider).provider('$$animateJsDriver', $$AnimateJsDriverProvider);
+ }).info({ angularVersion: '1.7.3' }).directive('ngAnimateSwap', ngAnimateSwapDirective).directive('ngAnimateChildren', $$AnimateChildrenDirective).factory('$$rAFScheduler', $$rAFSchedulerFactory).provider('$$animateQueue', $$AnimateQueueProvider).provider('$$animateCache', $$AnimateCacheProvider).provider('$$animation', $$AnimationProvider).provider('$animateCss', $AnimateCssProvider).provider('$$animateCssDriver', $$AnimateCssDriverProvider).provider('$$animateJs', $$AnimateJsProvider).provider('$$animateJsDriver', $$AnimateJsDriverProvider);
})(window, window.angular);
},{}],170:[function(require,module,exports){
@@ -34735,8 +34894,8 @@ module.exports = 'ngAnimate';
'use strict';
/**
- * @license AngularJS v1.6.8
- * (c) 2010-2017 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.7.3
+ * (c) 2010-2018 Google, Inc. http://angularjs.org
* License: MIT
*/
(function (window, angular) {
@@ -34757,6 +34916,7 @@ module.exports = 'ngAnimate';
var bind;
var extend;
var forEach;
+ var isArray;
var isDefined;
var lowercase;
var noop;
@@ -34783,12 +34943,11 @@ module.exports = 'ngAnimate';
* Sanitizes an html string by stripping all potentially dangerous tokens.
*
* The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
- * then serialized back to properly escaped html string. This means that no unsafe input can make
+ * then serialized back to a properly escaped HTML string. This means that no unsafe input can make
* it into the returned string.
*
* The whitelist for URL sanitization of attribute values is configured using the functions
- * `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider
- * `$compileProvider`}.
+ * `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link $compileProvider}.
*
* The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
*
@@ -34886,9 +35045,11 @@ module.exports = 'ngAnimate';
* Creates and configures {@link $sanitize} instance.
*/
function $SanitizeProvider() {
+ var hasBeenInstantiated = false;
var svgEnabled = false;
this.$get = ['$$sanitizeUri', function ($$sanitizeUri) {
+ hasBeenInstantiated = true;
if (svgEnabled) {
extend(validElements, svgElements);
}
@@ -34928,7 +35089,7 @@ module.exports = 'ngAnimate';
*
*
* @param {boolean=} flag Enable or disable SVG support in the sanitizer.
- * @returns {boolean|ng.$sanitizeProvider} Returns the currently configured value if called
+ * @returns {boolean|$sanitizeProvider} Returns the currently configured value if called
* without an argument or self for chaining otherwise.
*/
this.enableSvg = function (enableSvg) {
@@ -34940,6 +35101,103 @@ module.exports = 'ngAnimate';
}
};
+ /**
+ * @ngdoc method
+ * @name $sanitizeProvider#addValidElements
+ * @kind function
+ *
+ * @description
+ * Extends the built-in lists of valid HTML/SVG elements, i.e. elements that are considered safe
+ * and are not stripped off during sanitization. You can extend the following lists of elements:
+ *
+ * - `htmlElements`: A list of elements (tag names) to extend the current list of safe HTML
+ * elements. HTML elements considered safe will not be removed during sanitization. All other
+ * elements will be stripped off.
+ *
+ * - `htmlVoidElements`: This is similar to `htmlElements`, but marks the elements as
+ * "void elements" (similar to HTML
+ * [void elements](https://rawgit.com/w3c/html/html5.1-2/single-page.html#void-elements)). These
+ * elements have no end tag and cannot have content.
+ *
+ * - `svgElements`: This is similar to `htmlElements`, but for SVG elements. This list is only
+ * taken into account if SVG is {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for
+ * `$sanitize`.
+ *
+ *
+ * This method must be called during the {@link angular.Module#config config} phase. Once the
+ * `$sanitize` service has been instantiated, this method has no effect.
+ *
+ *
+ *
+ * Keep in mind that extending the built-in lists of elements may expose your app to XSS or
+ * other vulnerabilities. Be very mindful of the elements you add.
+ *
+ *
+ * @param {Array|Object} elements - A list of valid HTML elements or an object with one or
+ * more of the following properties:
+ * - **htmlElements** - `{Array}` - A list of elements to extend the current list of
+ * HTML elements.
+ * - **htmlVoidElements** - `{Array}` - A list of elements to extend the current list of
+ * void HTML elements; i.e. elements that do not have an end tag.
+ * - **svgElements** - `{Array}` - A list of elements to extend the current list of SVG
+ * elements. The list of SVG elements is only taken into account if SVG is
+ * {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for `$sanitize`.
+ *
+ * Passing an array (`[...]`) is equivalent to passing `{htmlElements: [...]}`.
+ *
+ * @return {$sanitizeProvider} Returns self for chaining.
+ */
+ this.addValidElements = function (elements) {
+ if (!hasBeenInstantiated) {
+ if (isArray(elements)) {
+ elements = { htmlElements: elements };
+ }
+
+ addElementsTo(svgElements, elements.svgElements);
+ addElementsTo(voidElements, elements.htmlVoidElements);
+ addElementsTo(validElements, elements.htmlVoidElements);
+ addElementsTo(validElements, elements.htmlElements);
+ }
+
+ return this;
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sanitizeProvider#addValidAttrs
+ * @kind function
+ *
+ * @description
+ * Extends the built-in list of valid attributes, i.e. attributes that are considered safe and are
+ * not stripped off during sanitization.
+ *
+ * **Note**:
+ * The new attributes will not be treated as URI attributes, which means their values will not be
+ * sanitized as URIs using `$compileProvider`'s
+ * {@link ng.$compileProvider#aHrefSanitizationWhitelist aHrefSanitizationWhitelist} and
+ * {@link ng.$compileProvider#imgSrcSanitizationWhitelist imgSrcSanitizationWhitelist}.
+ *
+ *
+ * This method must be called during the {@link angular.Module#config config} phase. Once the
+ * `$sanitize` service has been instantiated, this method has no effect.
+ *
+ *
+ *
+ * Keep in mind that extending the built-in list of attributes may expose your app to XSS or
+ * other vulnerabilities. Be very mindful of the attributes you add.
+ *
+ *
+ * @param {Array} attrs - A list of valid attributes.
+ *
+ * @returns {$sanitizeProvider} Returns self for chaining.
+ */
+ this.addValidAttrs = function (attrs) {
+ if (!hasBeenInstantiated) {
+ extend(validAttrs, arrayToMap(attrs, true));
+ }
+ return this;
+ };
+
//////////////////////////////////////////////////////////////////////////////////////////////////
// Private stuff
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -34947,8 +35205,9 @@ module.exports = 'ngAnimate';
bind = angular.bind;
extend = angular.extend;
forEach = angular.forEach;
+ isArray = angular.isArray;
isDefined = angular.isDefined;
- lowercase = angular.lowercase;
+ lowercase = angular.$$lowercase;
noop = angular.noop;
htmlParser = htmlParserImpl;
@@ -34971,45 +35230,48 @@ module.exports = 'ngAnimate';
// Safe Void Elements - HTML5
// http://dev.w3.org/html5/spec/Overview.html#void-elements
- var voidElements = toMap('area,br,col,hr,img,wbr');
+ var voidElements = stringToMap('area,br,col,hr,img,wbr');
// Elements that you can, intentionally, leave open (and which close themselves)
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
- var optionalEndTagBlockElements = toMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),
- optionalEndTagInlineElements = toMap('rp,rt'),
+ var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),
+ optionalEndTagInlineElements = stringToMap('rp,rt'),
optionalEndTagElements = extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
// Safe Block Elements - HTML5
- var blockElements = extend({}, optionalEndTagBlockElements, toMap('address,article,' + 'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + 'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul'));
+ var blockElements = extend({}, optionalEndTagBlockElements, stringToMap('address,article,' + 'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + 'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul'));
// Inline Elements - HTML5
- var inlineElements = extend({}, optionalEndTagInlineElements, toMap('a,abbr,acronym,b,' + 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' + 'samp,small,span,strike,strong,sub,sup,time,tt,u,var'));
+ var inlineElements = extend({}, optionalEndTagInlineElements, stringToMap('a,abbr,acronym,b,' + 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' + 'samp,small,span,strike,strong,sub,sup,time,tt,u,var'));
// SVG Elements
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
// They can potentially allow for arbitrary javascript to be executed. See #11290
- var svgElements = toMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' + 'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' + 'radialGradient,rect,stop,svg,switch,text,title,tspan');
+ var svgElements = stringToMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' + 'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' + 'radialGradient,rect,stop,svg,switch,text,title,tspan');
// Blocked Elements (will be stripped)
- var blockedElements = toMap('script,style');
+ var blockedElements = stringToMap('script,style');
var validElements = extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
//Attributes that have href and hence need to be sanitized
- var uriAttrs = toMap('background,cite,href,longdesc,src,xlink:href');
+ var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base');
- var htmlAttrs = toMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + 'valign,value,vspace,width');
+ var htmlAttrs = stringToMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + 'valign,value,vspace,width');
// SVG attributes (without "id" and "name" attributes)
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
- var svgAttrs = toMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
+ var svgAttrs = stringToMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
var validAttrs = extend({}, uriAttrs, svgAttrs, htmlAttrs);
- function toMap(str, lowercaseKeys) {
+ function stringToMap(str, lowercaseKeys) {
+ return arrayToMap(str.split(','), lowercaseKeys);
+ }
+
+ function arrayToMap(items, lowercaseKeys) {
var obj = {},
- items = str.split(','),
i;
for (i = 0; i < items.length; i++) {
obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;
@@ -35017,6 +35279,12 @@ module.exports = 'ngAnimate';
return obj;
}
+ function addElementsTo(elementsMap, newElements) {
+ if (newElements && newElements.length) {
+ extend(elementsMap, arrayToMap(newElements));
+ }
+ }
+
/**
* Create an inert document that contains the dirty HTML that needs sanitizing
* Depending upon browser support we use one of three strategies for doing this.
@@ -35294,7 +35562,7 @@ module.exports = 'ngAnimate';
}
// define ngSanitize module and register $sanitize service
- angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider).info({ angularVersion: '1.6.8' });
+ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider).info({ angularVersion: '1.7.3' });
/**
* @ngdoc filter
@@ -35502,9 +35770,9 @@ module.exports = 'ngSanitize';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/*!
- * angular-translate - v2.17.0 - 2017-12-21
+ * angular-translate - v2.18.1 - 2018-05-19
*
- * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT
+ * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
@@ -35557,9 +35825,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/*!
- * angular-translate - v2.17.0 - 2017-12-21
+ * angular-translate - v2.18.1 - 2018-05-19
*
- * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT
+ * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
@@ -36033,7 +36301,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
};
- var version = '2.17.0';
+ var version = '2.18.1';
// tries to determine the browsers language
var getFirstBrowserLanguage = function getFirstBrowserLanguage() {
@@ -39057,7 +39325,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* @description
* Translates given translation id either through attribute or DOM content.
- * Internally it uses `translate` filter to translate translation id. It possible to
+ * Internally it uses `translate` filter to translate translation id. It is possible to
* pass an optional `translate-values` object literal as string into translation id.
*
* @param {string=} translate namespace name which could be either string or interpolated string.
@@ -39111,7 +39379,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
compile: function compile() {
return {
pre: function pre(scope, iElement, iAttrs) {
- scope.translateNamespace = getTranslateNamespace(scope);
+ scope.translateNamespace = _getTranslateNamespace(scope);
if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {
scope.translateNamespace += iAttrs.translateNamespace;
@@ -39130,14 +39398,14 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @param scope
* @returns {string}
*/
- function getTranslateNamespace(scope) {
+ function _getTranslateNamespace(scope) {
'use strict';
if (scope.translateNamespace) {
return scope.translateNamespace;
}
if (scope.$parent) {
- return getTranslateNamespace(scope.$parent);
+ return _getTranslateNamespace(scope.$parent);
}
}
@@ -39325,8 +39593,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/**
- * @license AngularJS v1.6.8
- * (c) 2010-2017 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.7.3
+ * (c) 2010-2018 Google, Inc. http://angularjs.org
* License: MIT
*/
(function (window) {
@@ -39339,7 +39607,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*/
var minErrConfig = {
- objectMaxDepth: 5
+ objectMaxDepth: 5,
+ urlErrorParamsEnabled: true
};
/**
@@ -39362,12 +39631,21 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
* non-positive or non-numeric value, removes the max depth limit.
* Default: 5
+ *
+ * * `urlErrorParamsEnabled` **{Boolean}** - Specifies wether the generated error url will
+ * contain the parameters of the thrown error. Disabling the parameters can be useful if the
+ * generated error url is very long.
+ *
+ * Default: true. When used without argument, it returns the current value.
*/
function errorHandlingConfig(config) {
if (isObject(config)) {
if (isDefined(config.objectMaxDepth)) {
minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;
}
+ if (isDefined(config.urlErrorParamsEnabled) && isBoolean(config.urlErrorParamsEnabled)) {
+ minErrConfig.urlErrorParamsEnabled = config.urlErrorParamsEnabled;
+ }
} else {
return minErrConfig;
}
@@ -39386,7 +39664,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @description
*
* This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
+ * AngularJS. It can be called as follows:
*
* var exampleMinErr = minErr('example');
* throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
@@ -39414,6 +39692,11 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
function minErr(module, ErrorConstructor) {
ErrorConstructor = ErrorConstructor || Error;
+
+ var url = 'https://errors.angularjs.org/1.7.3/';
+ var regex = url.replace('.', '\\.') + '[\\s\\S]*';
+ var errRegExp = new RegExp(regex, 'g');
+
return function () {
var code = arguments[0],
template = arguments[1],
@@ -39424,20 +39707,27 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
paramPrefix,
i;
+ // A minErr message has two parts: the message itself and the url that contains the
+ // encoded message.
+ // The message's parameters can contain other error messages which also include error urls.
+ // To prevent the messages from getting too long, we strip the error urls from the parameters.
+
message += template.replace(/\{\d+\}/g, function (match) {
var index = +match.slice(1, -1);
if (index < templateArgs.length) {
- return templateArgs[index];
+ return templateArgs[index].replace(errRegExp, '');
}
return match;
});
- message += '\nhttp://errors.angularjs.org/1.6.8/' + (module ? module + '/' : '') + code;
+ message += '\n' + url + (module ? module + '/' : '') + code;
- for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
- message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]);
+ if (minErrConfig.urlErrorParamsEnabled) {
+ for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
+ message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]);
+ }
}
return new ErrorConstructor(message);
@@ -39465,8 +39755,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
lowercase,
uppercase,
- manualLowercase,
- manualUppercase,
nodeName_,
isArrayLike,
forEach,
@@ -39519,6 +39807,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
fromJson,
convertTimezoneToLocal,
timezoneToOffset,
+ addDateMinutes,
startingTag,
tryDecodeURIComponent,
parseKeyValue,
@@ -39572,15 +39861,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
- * @ngdoc function
- * @name angular.lowercase
- * @module ng
- * @kind function
- *
- * @deprecated
- * sinceVersion="1.5.0"
- * removeVersion="1.7.0"
- * Use [String.prototype.toLowerCase](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase) instead.
+ * @private
*
* @description Converts the specified string to lowercase.
* @param {string} string String to be converted to lowercase.
@@ -39591,15 +39872,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
};
/**
- * @ngdoc function
- * @name angular.uppercase
- * @module ng
- * @kind function
- *
- * @deprecated
- * sinceVersion="1.5.0"
- * removeVersion="1.7.0"
- * Use [String.prototype.toUpperCase](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) instead.
+ * @private
*
* @description Converts the specified string to uppercase.
* @param {string} string String to be converted to uppercase.
@@ -39609,29 +39882,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return isString(string) ? string.toUpperCase() : string;
};
- var manualLowercase = function manualLowercase(s) {
- /* eslint-disable no-bitwise */
- return isString(s) ? s.replace(/[A-Z]/g, function (ch) {
- return String.fromCharCode(ch.charCodeAt(0) | 32);
- }) : s;
- /* eslint-enable */
- };
- var manualUppercase = function manualUppercase(s) {
- /* eslint-disable no-bitwise */
- return isString(s) ? s.replace(/[a-z]/g, function (ch) {
- return String.fromCharCode(ch.charCodeAt(0) & ~32);
- }) : s;
- /* eslint-enable */
- };
-
- // 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. See https://github.com/angular/angular.js/issues/11387
- if ('i' !== 'I'.toLowerCase()) {
- lowercase = manualLowercase;
- uppercase = manualUppercase;
- }
-
var msie,
// holds major version number for IE, or NaN if UA is not IE.
jqLite,
@@ -39681,7 +39931,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// NodeList objects (with `item` method) and
// other objects with suitable length characteristics are array-like
- return isNumber(length) && (length >= 0 && (length - 1 in obj || obj instanceof Array) || typeof obj.item === 'function');
+ return isNumber(length) && (length >= 0 && length - 1 in obj || typeof obj.item === 'function');
}
/**
@@ -40094,12 +40344,14 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @kind function
*
* @description
- * Determines if a reference is an `Array`. Alias of Array.isArray.
+ * Determines if a reference is an `Array`.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Array`.
*/
- var isArray = Array.isArray;
+ function isArray(arr) {
+ return Array.isArray(arr) || arr instanceof Array;
+ }
/**
* @description
@@ -40616,7 +40868,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* used to force either jqLite by leaving ng-jq blank or setting the name of
* the jquery variable under window (eg. jQuery).
*
- * Since angular looks for this directive when it is loaded (doesn't wait for the
+ * Since AngularJS looks for this directive when it is loaded (doesn't wait for the
* DOMContentLoaded event), it must be placed on an element that comes before the script
* which loads angular. Also, only the first instance of `ng-jq` will be used and all
* others ignored.
@@ -40723,7 +40975,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* @description
* Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
- * stripped since angular uses this notation internally.
+ * stripped since AngularJS uses this notation internally.
*
* @param {Object|Array|Date|string|number|boolean} obj Input to be serialized into JSON.
* @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
@@ -40802,7 +41054,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*/
function startingTag(element) {
element = jqLite(element).clone().empty();
- var elemHtml = jqLite('
').append(element).html();
+ var elemHtml = jqLite('').append(element).html();
try {
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml.match(/^(<[^>]+>)/)[1].replace(/^<([\w-]+)/, function (match, nodeName) {
return '<' + lowercase(nodeName);
@@ -41139,7 +41391,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
});
if (appElement) {
if (!isAutoBootstrapAllowed) {
- window.console.error('Angular: disabling automatic bootstrap.
@@ -47240,11 +47627,11 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
it('should auto compile', function() {
var textarea = $('textarea');
var output = $('div[compile]');
- // The initial state reads 'Hello Angular'.
- expect(output.getText()).toBe('Hello Angular');
+ // The initial state reads 'Hello AngularJS'.
+ expect(output.getText()).toBe('Hello AngularJS');
textarea.clear();
textarea.sendKeys('{{name}}!');
- expect(output.getText()).toBe('Angular!');
+ expect(output.getText()).toBe('AngularJS!');
});
@@ -47298,7 +47685,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* 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.
+ * AngularJS automatically.
*
* If you need access to the bound view, there are two ways to do it:
*
@@ -47324,7 +47711,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
*
* For information on how the compiler works, see the
- * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
+ * {@link guide/compiler AngularJS HTML Compiler} section of the Developer Guide.
*
* @knownIssue
*
@@ -47334,7 +47721,378 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
compiled again. This is an undesired effect and can lead to misbehaving directives, performance issues,
and memory leaks. Refer to the Compiler Guide {@link guide/compiler#double-compilation-and-how-to-avoid-it
section on double compilation} for an in-depth explanation and ways to avoid it.
+
+ * @knownIssue
+
+ ### Issues with `replace: true`
+ *
+ *
+ * **Note**: {@link $compile#-replace- `replace: true`} is deprecated and not recommended to use,
+ * mainly due to the issues listed here. It has been completely removed in the new Angular.
+ *
+ *
+ * #### Attribute values are not merged
+ *
+ * When a `replace` directive encounters the same attribute on the original and the replace node,
+ * it will simply deduplicate the attribute and join the values with a space or with a `;` in case of
+ * the `style` attribute.
+ * ```html
+ * Original Node:
+ * Replace Template:
+ * Result:
+ * ```
+ *
+ * That means attributes that contain AngularJS expressions will not be merged correctly, e.g.
+ * {@link ngShow} or {@link ngClass} will cause a {@link $parse} error:
+ *
+ * ```html
+ * Original Node:
+ * Replace Template:
+ * Result:
+ * ```
+ *
+ * See issue [#5695](https://github.com/angular/angular.js/issues/5695).
+ *
+ * #### Directives are not deduplicated before compilation
+ *
+ * When the original node and the replace template declare the same directive(s), they will be
+ * {@link guide/compiler#double-compilation-and-how-to-avoid-it compiled twice} because the compiler
+ * does not deduplicate them. In many cases, this is not noticable, but e.g. {@link ngModel} will
+ * attach `$formatters` and `$parsers` twice.
+ *
+ * See issue [#2573](https://github.com/angular/angular.js/issues/2573).
+ *
+ * #### `transclude: element` in the replace template root can have unexpected effects
+ *
+ * When the replace template has a directive at the root node that uses
+ * {@link $compile#-transclude- `transclude: element`}, e.g.
+ * {@link ngIf} or {@link ngRepeat}, the DOM structure or scope inheritance can be incorrect.
+ * See the following issues:
+ *
+ * - Incorrect scope on replaced element:
+ * [#9837](https://github.com/angular/angular.js/issues/9837)
+ * - Different DOM between `template` and `templateUrl`:
+ * [#10612](https://github.com/angular/angular.js/issues/14326)
+ *
+ */
+
+ /**
+ * @ngdoc directive
+ * @name ngProp
+ * @restrict A
+ * @element ANY
+ *
+ * @usage
+ *
+ * ```html
+ *
+ *
+ * ```
+ *
+ * or with uppercase letters in property (e.g. "propName"):
+ *
+ *
+ * ```html
+ *
+ *
+ * ```
+ *
+ *
+ * @description
+ * The `ngProp` directive binds an expression to a DOM element property.
+ * `ngProp` allows writing to arbitrary properties by including
+ * the property name in the attribute, e.g. `ng-prop-value="'my value'"` binds 'my value' to
+ * the `value` property.
+ *
+ * Usually, it's not necessary to write to properties in AngularJS, as the built-in directives
+ * handle the most common use cases (instead of the above example, you would use {@link ngValue}).
+ *
+ * However, [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements)
+ * often use custom properties to hold data, and `ngProp` can be used to provide input to these
+ * custom elements.
+ *
+ * ## Binding to camelCase properties
+ *
+ * Since HTML attributes are case-insensitive, camelCase properties like `innerHTML` must be escaped.
+ * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so
+ * `innerHTML` must be written as `ng-prop-inner_h_t_m_l="expression"` (Note that this is just an
+ * example, and for binding HTML {@link ngBindHtml} should be used.
+ *
+ * ## Security
+ *
+ * Binding expressions to arbitrary properties poses a security risk, as properties like `innerHTML`
+ * can insert potentially dangerous HTML into the application, e.g. script tags that execute
+ * malicious code.
+ * For this reason, `ngProp` applies Strict Contextual Escaping with the {@link ng.$sce $sce service}.
+ * This means vulnerable properties require their content to be "trusted", based on the
+ * context of the property. For example, the `innerHTML` is in the `HTML` context, and the
+ * `iframe.src` property is in the `RESOURCE_URL` context, which requires that values written to
+ * this property are trusted as a `RESOURCE_URL`.
+ *
+ * This can be set explicitly by calling $sce.trustAs(type, value) on the value that is
+ * trusted before passing it to the `ng-prop-*` directive. There are exist shorthand methods for
+ * each context type in the form of {@link ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl()} et al.
+ *
+ * In some cases you can also rely upon automatic sanitization of untrusted values - see below.
+ *
+ * Based on the context, other options may exist to mark a value as trusted / configure the behavior
+ * of {@link ng.$sce}. For example, to restrict the `RESOURCE_URL` context to specific origins, use
+ * the {@link $sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist()}
+ * and {@link $sceDelegateProvider#resourceUrlBlacklist resourceUrlBlacklist()}.
+ *
+ * {@link ng.$sce#what-trusted-context-types-are-supported- Find out more about the different context types}.
+ *
+ * ### HTML Sanitization
+ *
+ * By default, `$sce` will throw an error if it detects untrusted HTML content, and will not bind the
+ * content.
+ * However, if you include the {@link ngSanitize ngSanitize module}, it will try to sanitize the
+ * potentially dangerous HTML, e.g. strip non-whitelisted tags and attributes when binding to
+ * `innerHTML`.
+ *
+ * @example
+ * ### Binding to different contexts
+ *
+ *
+ *
+ * angular.module('exampleNgProp', [])
+ * .component('main', {
+ * templateUrl: 'main.html',
+ * controller: function($sce) {
+ * this.safeContent = 'Safe content';
+ * this.unsafeContent = '';
+ * this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent);
+ * }
+ * });
+ *
+ *
+ *
+ *
+ * Binding to a property without security context:
+ *
+ * innerText (safeContent)
+ *
+ *
+ *
+ * "Safe" content that requires a security context will throw because the contents could potentially be dangerous ...
+ *
+ * innerHTML (safeContent)
+ *
+ *
+ *
+ * ... so that actually dangerous content cannot be executed:
+ *
+ * innerHTML (unsafeContent)
+ *
+ *
+ *
+ * ... but unsafe Content that has been trusted explicitly works - only do this if you are 100% sure!
+ *
+ * innerHTML (trustedUnsafeContent)
+ *
+ * "Safe" content will be sanitized ...
+ *
+ * innerHTML (safeContent)
+ *
+ *
+ *
+ * ... as will dangerous content:
+ *
+ * innerHTML (unsafeContent)
+ *
+ *
+ *
+ * ... and content that has been trusted explicitly works the same as without ngSanitize:
+ *
+ * innerHTML (trustedUnsafeContent)
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * .prop-unit {
+ * margin-bottom: 10px;
+ * }
+ *
+ * .prop-binding {
+ * min-height: 30px;
+ * border: 1px solid blue;
+ * }
+ *
+ * .prop-note {
+ * font-family: Monospace;
+ * }
+ *
+ *
+ *
+ */
+
+ /** @ngdoc directive
+ * @name ngOn
+ * @restrict A
+ * @element ANY
+ *
+ * @usage
+ *
+ * ```html
+ *
+ *
+ * ```
+ *
+ * or with uppercase letters in property (e.g. "eventName"):
+ *
+ *
+ * ```html
+ *
+ *
+ * ```
+ *
+ * @description
+ * The `ngOn` directive adds an event listener to a DOM element via
+ * {@link angular.element angular.element().on()}, and evaluates an expression when the event is
+ * fired.
+ * `ngOn` allows adding listeners for arbitrary events by including
+ * the event name in the attribute, e.g. `ng-on-drop="onDrop()"` executes the 'onDrop()' expression
+ * when the `drop` event is fired.
+ *
+ * AngularJS provides specific directives for many events, such as {@link ngClick}, so in most
+ * cases it is not necessary to use `ngOn`. However, AngularJS does not support all events
+ * (e.g. the `drop` event in the example above), and new events might be introduced in later DOM
+ * standards.
+ *
+ * Another use-case for `ngOn` is listening to
+ * [custom events](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events)
+ * fired by
+ * [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements).
+ *
+ * ## Binding to camelCase properties
+ *
+ * Since HTML attributes are case-insensitive, camelCase properties like `myEvent` must be escaped.
+ * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so
+ * `myEvent` must be written as `ng-on-my_event="expression"`.
+ *
+ * @example
+ * ### Bind to built-in DOM events
+ *
+ *
+ *
+ * angular.module('exampleNgOn', [])
+ * .component('main', {
+ * templateUrl: 'main.html',
+ * controller: function() {
+ * this.clickCount = 0;
+ * this.mouseoverCount = 0;
+ *
+ * this.loadingState = 0;
+ * }
+ * });
+ *
+ *
+ *
+ * This is equivalent to `ngClick` and `ngMouseover`:
+ *
+ * clickCount: {{$ctrl.clickCount}}
+ * mouseover: {{$ctrl.mouseoverCount}}
+ *
+ *
+ *
+ * For the `error` and `load` event on images no built-in AngularJS directives exist:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
*
+ *
+ * @example
+ * ### Bind to custom DOM events
+ *
+ *
+ *
+ * angular.module('exampleNgOn', [])
+ * .component('main', {
+ * templateUrl: 'main.html',
+ * controller: function() {
+ * this.eventLog = '';
+ *
+ * this.listener = function($event) {
+ * this.eventLog = 'Event with type "' + $event.type + '" fired at ' + $event.detail;
+ * };
+ * }
+ * })
+ * .component('childComponent', {
+ * templateUrl: 'child.html',
+ * controller: function($element) {
+ * this.fireEvent = function() {
+ * var event = new CustomEvent('customtype', { detail: new Date()});
+ *
+ * $element[0].dispatchEvent(event);
+ * };
+ * }
+ * });
+ *
+ *
+ *
+ * Event log: {{$ctrl.eventLog}}
+ *
+ *
+
+ *
+ *
+ *
+ *
+ *
*/
var $compileMinErr = minErr('$compile');
@@ -47365,11 +48123,13 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var bindingCache = createMap();
function parseIsolateBindings(scope, directiveName, isController) {
- var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*([\w$]*)\s*$/;
+ var LOCAL_REGEXP = /^([@&]|[=<](\*?))(\??)\s*([\w$]*)$/;
var bindings = createMap();
forEach(scope, function (definition, scopeName) {
+ definition = definition.trim();
+
if (definition in bindingCache) {
bindings[scopeName] = bindingCache[definition];
return;
@@ -47633,7 +48393,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// TODO(pete) remove the following `forEach` before we release 1.6.0
// The component-router@0.2.0 looks for the annotations on the controller constructor
- // Nothing in Angular looks for annotations on the factory function but we can't remove
+ // Nothing in AngularJS looks for annotations on the factory function but we can't remove
// it from 1.5.x yet.
// Copy any annotation properties (starting with $) over to the factory and controller constructor functions
@@ -47745,56 +48505,23 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return debugInfoEnabled;
};
- /**
- * @ngdoc method
- * @name $compileProvider#preAssignBindingsEnabled
- *
- * @param {boolean=} enabled update the preAssignBindingsEnabled state if provided, otherwise just return the
- * current preAssignBindingsEnabled state
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- *
- * @kind function
- *
- * @description
- * Call this method to enable/disable whether directive controllers are assigned bindings before
- * calling the controller's constructor.
- * If enabled (true), the compiler assigns the value of each of the bindings to the
- * properties of the controller object before the constructor of this object is called.
- *
- * If disabled (false), the compiler calls the constructor first before assigning bindings.
- *
- * The default value is false.
- *
- * @deprecated
- * sinceVersion="1.6.0"
- * removeVersion="1.7.0"
- *
- * This method and the option to assign the bindings before calling the controller's constructor
- * will be removed in v1.7.0.
- */
- var preAssignBindingsEnabled = false;
- this.preAssignBindingsEnabled = function (enabled) {
- if (isDefined(enabled)) {
- preAssignBindingsEnabled = enabled;
- return this;
- }
- return preAssignBindingsEnabled;
- };
-
/**
* @ngdoc method
* @name $compileProvider#strictComponentBindingsEnabled
*
- * @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided, otherwise just return the
- * current strictComponentBindingsEnabled state
+ * @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided,
+ * otherwise return the current strictComponentBindingsEnabled state.
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*
* @kind function
*
* @description
- * Call this method to enable/disable strict component bindings check. If enabled, the compiler will enforce that
- * for all bindings of a component that are not set as optional with `?`, an attribute needs to be provided
- * on the component's HTML tag.
+ * Call this method to enable / disable the strict component bindings check. If enabled, the
+ * compiler will enforce that all scope / controller bindings of a
+ * {@link $compileProvider#directive directive} / {@link $compileProvider#component component}
+ * that are not set as optional with `?`, must be provided when the directive is instantiated.
+ * If not provided, the compiler will throw the
+ * {@link error/$compile/missingattr $compile:missingattr error}.
*
* The default value is false.
*/
@@ -47892,7 +48619,59 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return cssClassDirectivesEnabledConfig;
};
- this.$get = ['$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri', function ($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, $controller, $rootScope, $sce, $animate, $$sanitizeUri) {
+ /**
+ * The security context of DOM Properties.
+ * @private
+ */
+ var PROP_CONTEXTS = createMap();
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#addPropertySecurityContext
+ * @description
+ *
+ * Defines the security context for DOM properties bound by ng-prop-*.
+ *
+ * @param {string} elementName The element name or '*' to match any element.
+ * @param {string} propertyName The DOM property name.
+ * @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL`
+ * @returns {object} `this` for chaining
+ */
+ this.addPropertySecurityContext = function (elementName, propertyName, ctx) {
+ var key = elementName.toLowerCase() + '|' + propertyName.toLowerCase();
+
+ if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) {
+ throw $compileMinErr('ctxoverride', 'Property context \'{0}.{1}\' already set to \'{2}\', cannot override to \'{3}\'.', elementName, propertyName, PROP_CONTEXTS[key], ctx);
+ }
+
+ PROP_CONTEXTS[key] = ctx;
+ return this;
+ };
+
+ /* Default property contexts.
+ *
+ * Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58
+ * Changing:
+ * - SecurityContext.* => SCE_CONTEXTS/$sce.*
+ * - STYLE => CSS
+ * - various URL => MEDIA_URL
+ * - *|formAction, form|action URL => RESOURCE_URL (like the attribute)
+ */
+ (function registerNativePropertyContexts() {
+ function registerContext(ctx, values) {
+ forEach(values, function (v) {
+ PROP_CONTEXTS[v.toLowerCase()] = ctx;
+ });
+ }
+
+ registerContext(SCE_CONTEXTS.HTML, ['iframe|srcdoc', '*|innerHTML', '*|outerHTML']);
+ registerContext(SCE_CONTEXTS.CSS, ['*|style']);
+ registerContext(SCE_CONTEXTS.URL, ['area|href', 'area|ping', 'a|href', 'a|ping', 'blockquote|cite', 'body|background', 'del|cite', 'input|src', 'ins|cite', 'q|cite']);
+ registerContext(SCE_CONTEXTS.MEDIA_URL, ['audio|src', 'img|src', 'img|srcset', 'source|src', 'source|srcset', 'track|src', 'video|src', 'video|poster']);
+ registerContext(SCE_CONTEXTS.RESOURCE_URL, ['*|formAction', 'applet|code', 'applet|codebase', 'base|href', 'embed|src', 'frame|src', 'form|action', 'head|profile', 'html|manifest', 'iframe|src', 'link|href', 'media|src', 'object|codebase', 'object|data', 'script|src']);
+ })();
+
+ this.$get = ['$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', '$controller', '$rootScope', '$sce', '$animate', function ($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, $controller, $rootScope, $sce, $animate) {
var SIMPLE_ATTR_NAME = /^\w/;
var specialAttrHolder = window.document.createElement('div');
@@ -47915,25 +48694,71 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
// We must run this hook in an apply since the $$postDigest runs outside apply
$rootScope.$apply(function () {
- var errors = [];
for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) {
try {
onChangesQueue[i]();
} catch (e) {
- errors.push(e);
+ $exceptionHandler(e);
}
}
// Reset the queue to trigger a new schedule next time there is a change
onChangesQueue = undefined;
- if (errors.length) {
- throw errors;
- }
});
} finally {
onChangesTtl++;
}
}
+ function sanitizeSrcset(value, invokeType) {
+ if (!value) {
+ return value;
+ }
+ if (!isString(value)) {
+ throw $compileMinErr('srcset', 'Can\'t pass trusted values to `{0}`: "{1}"', invokeType, value.toString());
+ }
+
+ // Such values are a bit too complex to handle automatically inside $sce.
+ // Instead, we sanitize each of the URIs individually, which works, even dynamically.
+
+ // It's not possible to work around this using `$sce.trustAsMediaUrl`.
+ // If you want to programmatically set explicitly trusted unsafe URLs, you should use
+ // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
+ // `ng-bind-html` directive.
+
+ var result = '';
+
+ // first check if there are spaces because it's not the same pattern
+ var trimmedSrcset = trim(value);
+ // ( 999x ,| 999w ,| ,|, )
+ var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
+ var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
+
+ // split srcset into tuple of uri and descriptor except for the last item
+ var rawUris = trimmedSrcset.split(pattern);
+
+ // for each tuples
+ var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
+ for (var i = 0; i < nbrUrisWith2parts; i++) {
+ var innerIdx = i * 2;
+ // sanitize the uri
+ result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
+ // add the descriptor
+ result += ' ' + trim(rawUris[innerIdx + 1]);
+ }
+
+ // split the last item into uri and descriptor
+ var lastTuple = trim(rawUris[i * 2]).split(/\s/);
+
+ // sanitize the last uri
+ result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));
+
+ // and add the last descriptor if any
+ if (lastTuple.length === 2) {
+ result += ' ' + trim(lastTuple[1]);
+ }
+ return result;
+ }
+
function Attributes(element, attributesToCopy) {
if (attributesToCopy) {
var keys = Object.keys(attributesToCopy);
@@ -48037,8 +48862,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*/
$set: function $set(key, value, writeAttr, attrName) {
// TODO: decide whether or not to throw an error if "class"
- //is set through this function since it may cause $updateClass to
- //become unstable.
+ // is set through this function since it may cause $updateClass to
+ // become unstable.
var node = this.$$element[0],
booleanKey = getBooleanAttrName(node, key),
@@ -48068,43 +48893,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
nodeName = nodeName_(this.$$element);
- if (nodeName === 'a' && (key === 'href' || key === 'xlinkHref') || nodeName === 'img' && key === 'src') {
- // sanitize a[href] and img[src] values
- this[key] = value = $$sanitizeUri(value, key === 'src');
- } else if (nodeName === 'img' && key === 'srcset' && isDefined(value)) {
- // sanitize img[srcset] values
- var result = '';
-
- // first check if there are spaces because it's not the same pattern
- var trimmedSrcset = trim(value);
- // ( 999x ,| 999w ,| ,|, )
- var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
- var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
-
- // split srcset into tuple of uri and descriptor except for the last item
- var rawUris = trimmedSrcset.split(pattern);
-
- // for each tuples
- var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
- for (var i = 0; i < nbrUrisWith2parts; i++) {
- var innerIdx = i * 2;
- // sanitize the uri
- result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
- // add the descriptor
- result += ' ' + trim(rawUris[innerIdx + 1]);
- }
-
- // split the last item into uri and descriptor
- var lastTuple = trim(rawUris[i * 2]).split(/\s/);
-
- // sanitize the last uri
- result += $$sanitizeUri(trim(lastTuple[0]), true);
-
- // and add the last descriptor if any
- if (lastTuple.length === 2) {
- result += ' ' + trim(lastTuple[1]);
- }
- this[key] = value = result;
+ // Sanitize img[srcset] values.
+ if (nodeName === 'img' && key === 'srcset') {
+ this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)');
}
if (writeAttr !== false) {
@@ -48197,7 +48988,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
denormalizeTemplate = startSymbol === '{{' && endSymbol === '}}' ? identity : function denormalizeTemplate(template) {
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
},
- NG_ATTR_BINDING = /^ngAttr[A-Z]/;
+ NG_PREFIX_BINDING = /^ng(Attr|Prop|On)([A-Z].*)$/;
var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
@@ -48284,7 +49075,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// might change, so we need to recreate the namespace adapted compileNodes
// for call to the link function.
// Note: This will already clone the nodes...
- $linkNode = jqLite(wrapTemplate(namespace, jqLite('
').append($compileNodes).html()));
+ $linkNode = jqLite(wrapTemplate(namespace, jqLite('').append($compileNodes).html()));
} else if (cloneConnectFn) {
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
// and sometimes changes the structure of the DOM.
@@ -48516,40 +49307,64 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
addDirective(directives, directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective);
// iterate over the attributes
- for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
+ for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
var attrStartName = false;
var attrEndName = false;
+ var isNgAttr = false,
+ isNgProp = false,
+ isNgEvent = false;
+ var multiElementMatch;
+
attr = nAttrs[j];
name = attr.name;
value = attr.value;
- // support ngAttr attribute binding
- ngAttrName = directiveNormalize(name);
- isNgAttr = NG_ATTR_BINDING.test(ngAttrName);
- if (isNgAttr) {
- name = name.replace(PREFIX_REGEXP, '').substr(8).replace(/_(.)/g, function (match, letter) {
+ nName = directiveNormalize(name.toLowerCase());
+
+ // Support ng-attr-*, ng-prop-* and ng-on-*
+ if (ngPrefixMatch = nName.match(NG_PREFIX_BINDING)) {
+ isNgAttr = ngPrefixMatch[1] === 'Attr';
+ isNgProp = ngPrefixMatch[1] === 'Prop';
+ isNgEvent = ngPrefixMatch[1] === 'On';
+
+ // Normalize the non-prefixed name
+ name = name.replace(PREFIX_REGEXP, '').toLowerCase().substr(4 + ngPrefixMatch[1].length).replace(/_(.)/g, function (match, letter) {
return letter.toUpperCase();
});
- }
- var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
- if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
+ // Support *-start / *-end multi element directives
+ } else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) {
attrStartName = name;
attrEndName = name.substr(0, name.length - 5) + 'end';
name = name.substr(0, name.length - 6);
}
- nName = directiveNormalize(name.toLowerCase());
- attrsMap[nName] = name;
- if (isNgAttr || !attrs.hasOwnProperty(nName)) {
+ if (isNgProp || isNgEvent) {
attrs[nName] = value;
- if (getBooleanAttrName(node, nName)) {
- attrs[nName] = true; // presence means true
+ attrsMap[nName] = attr.name;
+
+ if (isNgProp) {
+ addPropertyDirective(node, directives, nName, name);
+ } else {
+ addEventDirective(directives, nName, name);
+ }
+ } else {
+ // Update nName for cases where a prefix was removed
+ // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-*
+ nName = directiveNormalize(name.toLowerCase());
+ attrsMap[nName] = name;
+
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
+ attrs[nName] = value;
+ if (getBooleanAttrName(node, nName)) {
+ attrs[nName] = true; // presence means true
+ }
}
+
+ addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
+ addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, attrEndName);
}
- addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
- addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, attrEndName);
}
if (nodeName === 'input' && node.getAttribute('type') === 'hidden') {
@@ -48815,17 +49630,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
compileNode = $compileNode[0];
replaceWith(jqCollection, sliceArgs($template), compileNode);
- // Support: Chrome < 50
- // https://github.com/angular/angular.js/issues/14041
-
- // In the versions of V8 prior to Chrome 50, the document fragment that is created
- // in the `replaceWith` function is improperly garbage collected despite still
- // being referenced by the `parentNode` property of all of the child nodes. By adding
- // a reference to the fragment via a different property, we can avoid that incorrect
- // behavior.
- // TODO: remove this line after Chrome 50 has been released
- $template[0].$$parentNode = $template[0].parentNode;
-
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority, replaceDirective && replaceDirective.name, {
// Don't pass in:
// - controllerDirectives - otherwise we'll create duplicates controllers
@@ -48846,7 +49650,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// We have transclusion slots,
// collect them up, compile them and store their transclusion functions
- $template = [];
+ $template = window.document.createDocumentFragment();
var slotMap = createMap();
var filledSlots = createMap();
@@ -48874,10 +49678,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var slotName = slotMap[directiveNormalize(nodeName_(node))];
if (slotName) {
filledSlots[slotName] = true;
- slots[slotName] = slots[slotName] || [];
- slots[slotName].push(node);
+ slots[slotName] = slots[slotName] || window.document.createDocumentFragment();
+ slots[slotName].appendChild(node);
} else {
- $template.push(node);
+ $template.appendChild(node);
}
});
@@ -48891,9 +49695,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
for (var slotName in slots) {
if (slots[slotName]) {
// Only define a transclusion function if the slot was filled
- slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);
+ var slotCompileNodes = jqLite(slots[slotName].childNodes);
+ slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slotCompileNodes, transcludeFn);
}
}
+
+ $template = jqLite($template.childNodes);
}
$compileNode.empty(); // clear contents
@@ -49072,29 +49879,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
var controller = elementControllers[name];
var bindings = controllerDirective.$$bindings.bindToController;
- if (preAssignBindingsEnabled) {
- if (bindings) {
- controller.bindingInfo = initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- } else {
- controller.bindingInfo = {};
- }
-
- var controllerResult = controller();
- if (controllerResult !== controller.instance) {
- // If the controller constructor has a return value, overwrite the instance
- // from setupControllers
- controller.instance = controllerResult;
- $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
- if (controller.bindingInfo.removeWatches) {
- controller.bindingInfo.removeWatches();
- }
- controller.bindingInfo = initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- }
- } else {
- controller.instance = controller();
- $element.data('$' + controllerDirective.name + 'Controller', controller.instance);
- controller.bindingInfo = initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- }
+ controller.instance = controller();
+ $element.data('$' + controllerDirective.name + 'Controller', controller.instance);
+ controller.bindingInfo = initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
}
// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
@@ -49223,7 +50010,14 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
if (!value) {
var dataName = '$' + name + 'Controller';
- value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
+
+ if (inheritType === '^^' && $element[0] && $element[0].nodeType === NODE_TYPE_DOCUMENT) {
+ // inheritedData() uses the documentElement when it finds the document, so we would
+ // require from the element itself.
+ value = null;
+ } else {
+ value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
+ }
}
if (!value && !optional) {
@@ -49550,27 +50344,91 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
}
- function getTrustedContext(node, attrNormalizedName) {
+ function getTrustedAttrContext(nodeName, attrNormalizedName) {
if (attrNormalizedName === 'srcdoc') {
return $sce.HTML;
}
- var tag = nodeName_(node);
- // All tags with src attributes require a RESOURCE_URL value, except for
- // img and various html5 media tags.
+ // All nodes with src attributes require a RESOURCE_URL value, except for
+ // img and various html5 media nodes, which require the MEDIA_URL context.
if (attrNormalizedName === 'src' || attrNormalizedName === 'ngSrc') {
- if (['img', 'video', 'audio', 'source', 'track'].indexOf(tag) === -1) {
+ if (['img', 'video', 'audio', 'source', 'track'].indexOf(nodeName) === -1) {
return $sce.RESOURCE_URL;
}
- // maction[xlink:href] can source SVG. It's not limited to .
- } else if (attrNormalizedName === 'xlinkHref' || tag === 'form' && attrNormalizedName === 'action' ||
+ return $sce.MEDIA_URL;
+ } else if (attrNormalizedName === 'xlinkHref') {
+ // Some xlink:href are okay, most aren't
+ if (nodeName === 'image') return $sce.MEDIA_URL;
+ if (nodeName === 'a') return $sce.URL;
+ return $sce.RESOURCE_URL;
+ } else if (
+ // Formaction
+ nodeName === 'form' && attrNormalizedName === 'action' ||
+ // If relative URLs can go where they are not expected to, then
+ // all sorts of trust issues can arise.
+ nodeName === 'base' && attrNormalizedName === 'href' ||
// links can be stylesheets or imports, which can run script in the current origin
- tag === 'link' && attrNormalizedName === 'href') {
+ nodeName === 'link' && attrNormalizedName === 'href') {
return $sce.RESOURCE_URL;
+ } else if (nodeName === 'a' && (attrNormalizedName === 'href' || attrNormalizedName === 'ngHref')) {
+ return $sce.URL;
}
}
+ function getTrustedPropContext(nodeName, propNormalizedName) {
+ var prop = propNormalizedName.toLowerCase();
+ return PROP_CONTEXTS[nodeName + '|' + prop] || PROP_CONTEXTS['*|' + prop];
+ }
+
+ function sanitizeSrcsetPropertyValue(value) {
+ return sanitizeSrcset($sce.valueOf(value), 'ng-prop-srcset');
+ }
+ function addPropertyDirective(node, directives, attrName, propName) {
+ if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) {
+ throw $compileMinErr('nodomevents', 'Property bindings for HTML DOM event properties are disallowed');
+ }
+
+ var nodeName = nodeName_(node);
+ var trustedContext = getTrustedPropContext(nodeName, propName);
+
+ var sanitizer = identity;
+ // Sanitize img[srcset] + source[srcset] values.
+ if (propName === 'srcset' && (nodeName === 'img' || nodeName === 'source')) {
+ sanitizer = sanitizeSrcsetPropertyValue;
+ } else if (trustedContext) {
+ sanitizer = $sce.getTrusted.bind($sce, trustedContext);
+ }
+
+ directives.push({
+ priority: 100,
+ compile: function ngPropCompileFn(_, attr) {
+ var ngPropGetter = $parse(attr[attrName]);
+ var ngPropWatch = $parse(attr[attrName], function sceValueOf(val) {
+ // Unwrap the value to compare the actual inner safe value, not the wrapper object.
+ return $sce.valueOf(val);
+ });
+
+ return {
+ pre: function ngPropPreLinkFn(scope, $element) {
+ function applyPropValue() {
+ var propValue = ngPropGetter(scope);
+ $element.prop(propName, sanitizer(propValue));
+ }
+
+ applyPropValue();
+ scope.$watch(ngPropWatch, applyPropValue);
+ }
+ };
+ }
+ });
+ }
+
+ function addEventDirective(directives, attrName, eventName) {
+ directives.push(createEventDirective($parse, $rootScope, $exceptionHandler, attrName, eventName, /*forceAsync=*/false));
+ }
+
function addAttrInterpolateDirective(node, directives, value, name, isNgAttr) {
- var trustedContext = getTrustedContext(node, name);
+ var nodeName = nodeName_(node);
+ var trustedContext = getTrustedAttrContext(nodeName, name);
var mustHaveExpression = !isNgAttr;
var allOrNothing = ALL_OR_NOTHING_ATTRS[name] || isNgAttr;
@@ -49579,12 +50437,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// no interpolation found -> ignore
if (!interpolateFn) return;
- if (name === 'multiple' && nodeName_(node) === 'select') {
+ if (name === 'multiple' && nodeName === 'select') {
throw $compileMinErr('selmulti', 'Binding to the \'multiple\' attribute is not supported. Element: {0}', startingTag(node));
}
if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
- throw $compileMinErr('nodomevents', 'Interpolations for HTML DOM event attributes are disallowed. Please use the ' + 'ng- versions (such as ng-click instead of onclick) instead.');
+ throw $compileMinErr('nodomevents', 'Interpolations for HTML DOM event attributes are disallowed');
}
directives.push({
@@ -49688,7 +50546,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
if (jqLite.hasData(firstElementToRemove)) {
- // Copy over user data (that includes Angular's $scope etc.). Don't copy private
+ // Copy over user data (that includes AngularJS's $scope etc.). Don't copy private
// data here because there's no public interface in jQuery to do that and copying over
// event listeners (which is the main use of private data) wouldn't work anyway.
jqLite.data(newNode, jqLite.data(firstElementToRemove));
@@ -49767,7 +50625,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
// the value is there for use in the link fn
destination[scopeName] = $interpolate(lastValue)(scope);
} else if (isBoolean(lastValue)) {
- // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted
+ // If the attributes is one of the BOOLEAN_ATTR then AngularJS will have converted
// the value to boolean rather than a string, so we special case this situation
destination[scopeName] = lastValue;
}
@@ -49827,21 +50685,21 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
if (optional && !attrs[attrName]) break;
parentGet = $parse(attrs[attrName]);
- var deepWatch = parentGet.literal;
+ var isLiteral = parentGet.literal;
var initialValue = destination[scopeName] = parentGet(scope);
initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
- removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
+ removeWatch = scope[definition.collection ? '$watchCollection' : '$watch'](parentGet, function parentValueWatchAction(newValue, oldValue) {
if (oldValue === newValue) {
- if (oldValue === initialValue || deepWatch && equals(oldValue, initialValue)) {
+ if (oldValue === initialValue || isLiteral && equals(oldValue, initialValue)) {
return;
}
oldValue = initialValue;
}
recordChanges(scopeName, newValue, oldValue);
destination[scopeName] = newValue;
- }, deepWatch);
+ });
removeWatchCollection.push(removeWatch);
break;
@@ -49930,7 +50788,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @description
* A shared object between directive compile / linking functions which contains normalized DOM
* element attributes. The values reflect current binding state `{{ }}`. The normalization is
- * needed since all of these are treated as equivalent in Angular:
+ * needed since all of these are treated as equivalent in AngularJS:
*
* ```
*
@@ -50027,15 +50885,14 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @this
*
* @description
- * The {@link ng.$controller $controller service} is used by Angular to create new
+ * The {@link ng.$controller $controller service} is used by AngularJS to create new
* controllers.
*
* This provider allows controller registration via the
* {@link ng.$controllerProvider#register register} method.
*/
function $ControllerProvider() {
- var controllers = {},
- globals = false;
+ var controllers = {};
/**
* @ngdoc method
@@ -50063,21 +50920,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
};
- /**
- * @ngdoc method
- * @name $controllerProvider#allowGlobals
- * @description If called, allows `$controller` to find controller constructors on `window`
- *
- * @deprecated
- * sinceVersion="v1.3.0"
- * removeVersion="v1.7.0"
- * This method of finding controllers has been deprecated.
- */
- this.allowGlobals = function () {
- globals = true;
- };
-
- this.$get = ['$injector', '$window', function ($injector, $window) {
+ this.$get = ['$injector', function ($injector) {
/**
* @ngdoc service
@@ -50090,8 +50933,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* * check if a controller with given name is registered via `$controllerProvider`
* * check if evaluating the string on the current scope returns a constructor
- * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
- * `window` object (deprecated, not recommended)
*
* The string can use the `controller as property` syntax, where the controller instance is published
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
@@ -50127,7 +50968,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
constructor = match[1];
identifier = identifier || match[3];
- expression = controllers.hasOwnProperty(constructor) ? controllers[constructor] : getter(locals.$scope, constructor, true) || (globals ? getter($window, constructor, true) : undefined);
+ expression = controllers.hasOwnProperty(constructor) ? controllers[constructor] : getter(locals.$scope, constructor, true);
if (!expression) {
throw $controllerMinErr('ctrlreg', 'The controller with the name \'{0}\' is not registered.', constructor);
@@ -50254,7 +51095,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @this
*
* @description
- * Any uncaught exception in angular expressions is delegated to this service.
+ * Any uncaught exception in AngularJS expressions is delegated to this service.
* The default implementation simply delegates to `$log.error` which logs it into
* the browser console.
*
@@ -50355,7 +51196,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object)
*
* Note that serializer will sort the request parameters alphabetically.
- * */
+ */
this.$get = function () {
return function ngParamSerializer(params) {
@@ -50422,7 +51263,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* });
* ```
*
- * */
+ */
this.$get = function () {
return function jQueryLikeParamSerializer(params) {
if (!params) return '';
@@ -50431,7 +51272,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return parts.join('&');
function serialize(toSerialize, prefix, topLevel) {
- if (toSerialize === null || isUndefined(toSerialize)) return;
if (isArray(toSerialize)) {
forEach(toSerialize, function (value, index) {
serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
@@ -50441,7 +51281,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
serialize(value, prefix + (topLevel ? '' : '[') + key + (topLevel ? '' : ']'));
});
} else {
- parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
+ if (isFunction(toSerialize)) {
+ toSerialize = toSerialize();
+ }
+ parts.push(encodeUriQuery(prefix) + '=' + (toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));
}
}
};
@@ -50572,7 +51415,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* @description
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
- * */
+ */
function $HttpProvider() {
/**
* @ngdoc property
@@ -50626,7 +51469,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
*
- **/
+ */
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [defaultHttpResponseTransform],
@@ -50673,7 +51516,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
* otherwise, returns the current configured value.
- **/
+ */
this.useApplyAsync = function (value) {
if (isDefined(value)) {
useApplyAsync = !!value;
@@ -50694,9 +51537,51 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* array, on request, but reverse order, on response.
*
* {@link ng.$http#interceptors Interceptors detailed info}
- **/
+ */
var interceptorFactories = this.interceptors = [];
+ /**
+ * @ngdoc property
+ * @name $httpProvider#xsrfWhitelistedOrigins
+ * @description
+ *
+ * Array containing URLs whose origins are trusted to receive the XSRF token. See the
+ * {@link ng.$http#security-considerations Security Considerations} sections for more details on
+ * XSRF.
+ *
+ * **Note:** An "origin" consists of the [URI scheme](https://en.wikipedia.org/wiki/URI_scheme),
+ * the [hostname](https://en.wikipedia.org/wiki/Hostname) and the
+ * [port number](https://en.wikipedia.org/wiki/Port_(computer_networking). For `http:` and
+ * `https:`, the port number can be omitted if using th default ports (80 and 443 respectively).
+ * Examples: `http://example.com`, `https://api.example.com:9876`
+ *
+ *
+ * It is not possible to whitelist specific URLs/paths. The `path`, `query` and `fragment` parts
+ * of a URL will be ignored. For example, `https://foo.com/path/bar?query=baz#fragment` will be
+ * treated as `https://foo.com`, meaning that **all** requests to URLs starting with
+ * `https://foo.com/` will include the XSRF token.
+ *
+ *
+ * @example
+ *
+ * ```js
+ * // App served from `https://example.com/`.
+ * angular.
+ * module('xsrfWhitelistedOriginsExample', []).
+ * config(['$httpProvider', function($httpProvider) {
+ * $httpProvider.xsrfWhitelistedOrigins.push('https://api.example.com');
+ * }]).
+ * run(['$http', function($http) {
+ * // The XSRF token will be sent.
+ * $http.get('https://api.example.com/preferences').then(...);
+ *
+ * // The XSRF token will NOT be sent.
+ * $http.get('https://stats.example.com/activity').then(...);
+ * }]);
+ * ```
+ */
+ var xsrfWhitelistedOrigins = this.xsrfWhitelistedOrigins = [];
+
this.$get = ['$browser', '$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', '$sce', function ($browser, $httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector, $sce) {
var defaultCache = $cacheFactory('$http');
@@ -50717,6 +51602,11 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
reversedInterceptors.unshift(isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
});
+ /**
+ * A function to check request URLs against a list of allowed origins.
+ */
+ var urlIsAllowedOrigin = urlIsAllowedOriginFactory(xsrfWhitelistedOrigins);
+
/**
* @ngdoc service
* @kind function
@@ -50728,7 +51618,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @requires $injector
*
* @description
- * The `$http` service is a core Angular service that facilitates communication with the remote
+ * The `$http` service is a core AngularJS service that facilitates communication with the remote
* HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
* object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
*
@@ -50745,7 +51635,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
*
* ## General usage
* The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —
- * that is used to generate an HTTP request and returns a {@link ng.$q promise}.
+ * that is used to generate an HTTP request and returns a {@link ng.$q promise} that is
+ * resolved (request success) or rejected (request failure) with a
+ * {@link ng.$http#$http-returns response} object.
*
* ```js
* // Simple GET request example:
@@ -50761,24 +51653,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* });
* ```
*
- * 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.
- * - **statusText** – `{string}` – HTTP status text of the response.
- * - **xhrStatus** – `{string}` – Status of the XMLHttpRequest (`complete`, `error`, `timeout` or `abort`).
- *
- * A response status code between 200 and 299 is considered a success status and will result in
- * the success callback being called. Any response status code outside of that range is
- * considered an error status and will result in the error callback being called.
- * Also, status codes less than -1 are normalized to zero. -1 usually means the request was
- * aborted, e.g. using a `config.timeout`.
- * Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning
- * that the outcome (success or error) will be determined by the final response status code.
- *
*
* ## Shortcut methods
*
@@ -50867,7 +51741,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* which allows you to `push` or `unshift` a new transformation function into the transformation chain.
*
*
- * **Note:** Angular does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline.
+ * **Note:** AngularJS does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline.
* That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference).
* For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest
* function will be reflected on the scope and in any templates where the object is data-bound.
@@ -50884,7 +51758,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* You can augment or replace the default transformations by modifying these properties by adding to or
* replacing the array.
*
- * Angular provides the following default transformations:
+ * AngularJS provides the following default transformations:
*
* Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`) is
* an array with one function that does the following:
@@ -51057,7 +51931,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
* - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
*
- * Both server and the client must cooperate in order to eliminate these threats. Angular comes
+ * Both server and the client must cooperate in order to eliminate these threats. AngularJS comes
* pre-configured with strategies that address these issues, but for this to work backend server
* cooperation is required.
*
@@ -51067,7 +51941,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* allows third party website to turn your JSON resource URL into
* [JSONP](http://en.wikipedia.org/wiki/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.
+ * AngularJS will automatically strip the prefix before processing it as JSON.
*
* For example if your server needs to return:
* ```js
@@ -51080,34 +51954,51 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* ['one','two']
* ```
*
- * Angular will strip the prefix, before processing the JSON.
+ * AngularJS will strip the prefix, before processing the JSON.
*
*
* ### Cross Site Request Forgery (XSRF) Protection
*
* [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by
* which the attacker can trick an authenticated user into unknowingly executing actions on your
- * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
+ * website. AngularJS provides a mechanism to counter XSRF. When performing XHR requests, the
* $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an 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.
- * The header will not be set for cross-domain requests.
+ * header (by default `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
+ * server can verify that the cookie matches the `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 [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
* for added security.
*
- * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
- * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
- * or the per-request config object.
+ * The header will — by default — **not** be set for cross-domain requests. This
+ * prevents unauthorized servers (e.g. malicious or compromised 3rd-party APIs) from gaining
+ * access to your users' XSRF tokens and exposing them to Cross Site Request Forgery. If you
+ * want to, you can whitelist additional origins to also receive the XSRF token, by adding them
+ * to {@link ng.$httpProvider#xsrfWhitelistedOrigins xsrfWhitelistedOrigins}. This might be
+ * useful, for example, if your application, served from `example.com`, needs to access your API
+ * at `api.example.com`.
+ * See {@link ng.$httpProvider#xsrfWhitelistedOrigins $httpProvider.xsrfWhitelistedOrigins} for
+ * more details.
+ *
+ *
+ * **Warning**
+ * Only whitelist origins that you have control over and make sure you understand the
+ * implications of doing so.
+ *
+ *
+ * The name of the cookie and the header can be specified using the `xsrfCookieName` and
+ * `xsrfHeaderName` properties of either `$httpProvider.defaults` at config-time,
+ * `$http.defaults` at run-time, or the per-request config object.
+ *
+ * In order to prevent collisions in environments where multiple AngularJS apps share the
+ * same domain or subdomain, we recommend that each application uses a unique cookie name.
*
- * In order to prevent collisions in environments where multiple Angular apps share the
- * same domain or subdomain, we recommend that each application uses unique cookie name.
*
* @param {object} config Object describing the request to be made and how it should be
* processed. The object has following properties:
@@ -51153,14 +52044,44 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* See {@link $http#caching $http Caching} for more information.
* - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
* that should abort the request when resolved.
+ *
+ * A numerical timeout or a promise returned from {@link ng.$timeout $timeout}, will set
+ * the `xhrStatus` in the {@link $http#$http-returns response} to "timeout", and any other
+ * resolved promise will set it to "abort", following standard XMLHttpRequest behavior.
+ *
* - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
* XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
* for more information.
* - **responseType** - `{string}` - see
* [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
*
- * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
- * when the request succeeds or fails.
+ * @returns {HttpPromise} A {@link ng.$q `Promise}` that will be resolved (request success)
+ * or rejected (request failure) with a response object.
+ *
+ * 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.
+ * - **statusText** – `{string}` – HTTP status text of the response.
+ * - **xhrStatus** – `{string}` – Status of the XMLHttpRequest
+ * (`complete`, `error`, `timeout` or `abort`).
+ *
+ *
+ * A response status code between 200 and 299 is considered a success status
+ * and will result in the success callback being called. Any response status
+ * code outside of that range is considered an error status and will result
+ * in the error callback being called.
+ * Also, status codes less than -1 are normalized to zero. -1 usually means
+ * the request was aborted, e.g. using a `config.timeout`. More information
+ * about the status might be available in the `xhrStatus` property.
+ *
+ * Note that if the response is a redirect, XMLHttpRequest will transparently
+ * follow it, meaning that the outcome (success or error) will be determined
+ * by the final response status code.
*
*
* @property {Array.
*
- * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string} ngModel Assignable AngularJS 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
@@ -64747,7 +66250,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
* length.
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * value does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * value does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -64755,9 +66258,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
* start at the index of the last search's match, thus not taking the whole input value into
* account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * @param {string=} ngChange AngularJS expression to be executed when input changes due to user
* interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input.
* This parameter is ignored for input[type=password] controls, which will never trim the
* input.
*
@@ -64972,7 +66475,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @restrict AC
*
* @description
- * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
+ * The `ngBind` attribute tells AngularJS 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.
*
@@ -64980,7 +66483,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* `{{ expression }}` which is similar but less verbose.
*
* It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
- * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
+ * displayed by the browser in its raw state before AngularJS 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
@@ -65108,7 +66611,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
* the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
* To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
- * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
+ * ngSanitize} in your module's dependencies (not in core AngularJS). In order to use {@link ngSanitize}
* in your module's dependencies, you need to include "angular-sanitize.js" in your application.
*
* You may also bypass sanitization for values you know are safe. To do so, bind to
@@ -65263,13 +66766,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return {
restrict: 'AC',
link: function link(scope, element, attr) {
- var expression = attr[name].trim();
- var isOneTime = expression.charAt(0) === ':' && expression.charAt(1) === ':';
-
- var watchInterceptor = isOneTime ? toFlatValue : toClassString;
- var watchExpression = $parse(expression, watchInterceptor);
- var watchAction = isOneTime ? ngClassOneTimeWatchAction : ngClassWatchAction;
-
var classCounts = element.data('$classCounts');
var oldModulo = true;
var oldClassString;
@@ -65292,7 +66788,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
scope.$watch(indexWatchExpression, ngClassIndexWatchAction);
}
- scope.$watch(watchExpression, watchAction, isOneTime);
+ scope.$watch($parse(attr[name], toClassString), ngClassWatchAction);
function addClasses(classString) {
classString = digestClassCounts(split(classString), 1);
@@ -65334,9 +66830,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
}
function ngClassIndexWatchAction(newModulo) {
- // This watch-action should run before the `ngClass[OneTime]WatchAction()`, thus it
+ // This watch-action should run before the `ngClassWatchAction()`, thus it
// adds/removes `oldClassString`. If the `ngClass` expression has changed as well, the
- // `ngClass[OneTime]WatchAction()` will update the classes.
+ // `ngClassWatchAction()` will update the classes.
if (newModulo === selector) {
addClasses(oldClassString);
} else {
@@ -65346,14 +66842,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
oldModulo = newModulo;
}
- function ngClassOneTimeWatchAction(newClassValue) {
- var newClassString = toClassString(newClassValue);
-
- if (newClassString !== oldClassString) {
- ngClassWatchAction(newClassString);
- }
- }
-
function ngClassWatchAction(newClassString) {
if (oldModulo === selector) {
updateClasses(oldClassString, newClassString);
@@ -65400,34 +66888,6 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
return classString;
}
-
- function toFlatValue(classValue) {
- var flatValue = classValue;
-
- if (isArray(classValue)) {
- flatValue = classValue.map(toFlatValue);
- } else if (isObject(classValue)) {
- var hasUndefined = false;
-
- flatValue = Object.keys(classValue).filter(function (key) {
- var value = classValue[key];
-
- if (!hasUndefined && isUndefined(value)) {
- hasUndefined = true;
- }
-
- return value;
- });
-
- if (hasUndefined) {
- // Prevent the `oneTimeLiteralWatchInterceptor` from unregistering
- // the watcher, by including at least one `undefined` value.
- flatValue.push(undefined);
- }
- }
-
- return flatValue;
- }
}
/**
@@ -65469,6 +66929,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* |----------------------------------|-------------------------------------|
* | {@link ng.$animate#addClass addClass} | just before the class is applied to the element |
* | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |
+ * | {@link ng.$animate#setClass setClass} | just before classes are added and classes are removed from the element at the same time |
*
* ### ngClass and pre-existing CSS3 Transitions/Animations
The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
@@ -65629,6 +67090,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* This directive can be applied only within the scope of an
* {@link ng.directive:ngRepeat ngRepeat}.
*
+ * @animations
+ * | Animation | Occurs |
+ * |----------------------------------|-------------------------------------|
+ * | {@link ng.$animate#addClass addClass} | just before the class is applied to the element |
+ * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |
+ *
* @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.
@@ -65661,6 +67128,62 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
});
+ *
+ *
+ * @example
+ * An example on how to implement animations using `ngClassOdd`:
+ *
+
+
+
+
+
+
+
+
{{ item }}
+
+
+
+
+
+ .odd {
+ background: rgba(255, 255, 0, 0.25);
+ }
+
+ .odd-add, .odd-remove {
+ transition: 1.5s;
+ }
+
+
+ it('should add new entries to the beginning of the list', function() {
+ var button = element(by.buttonText('Add item'));
+ var rows = element.all(by.repeater('item in items'));
+
+ expect(rows.count()).toBe(4);
+ expect(rows.get(0).getText()).toBe('Item 3');
+ expect(rows.get(1).getText()).toBe('Item 2');
+
+ button.click();
+
+ expect(rows.count()).toBe(5);
+ expect(rows.get(0).getText()).toBe('Item 4');
+ expect(rows.get(1).getText()).toBe('Item 3');
+ });
+
+ it('should add odd class to odd entries', function() {
+ var button = element(by.buttonText('Add item'));
+ var rows = element.all(by.repeater('item in items'));
+
+ expect(rows.get(0).getAttribute('class')).toMatch(/odd/);
+ expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/);
+
+ button.click();
+
+ expect(rows.get(0).getAttribute('class')).toMatch(/odd/);
+ expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/);
+ });
+
+
*/
var ngClassOddDirective = classDirective('Odd', 0);
@@ -65677,6 +67200,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* This directive can be applied only within the scope of an
* {@link ng.directive:ngRepeat ngRepeat}.
*
+ * @animations
+ * | Animation | Occurs |
+ * |----------------------------------|-------------------------------------|
+ * | {@link ng.$animate#addClass addClass} | just before the class is applied to the element |
+ * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |
+ *
* @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.
@@ -65709,6 +67238,62 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
});
+ *
+ *
+ * @example
+ * An example on how to implement animations using `ngClassEven`:
+ *
+
+
+
+
+
+
+
+
{{ item }}
+
+
+
+
+
+ .even {
+ background: rgba(255, 255, 0, 0.25);
+ }
+
+ .even-add, .even-remove {
+ transition: 1.5s;
+ }
+
+
+ it('should add new entries to the beginning of the list', function() {
+ var button = element(by.buttonText('Add item'));
+ var rows = element.all(by.repeater('item in items'));
+
+ expect(rows.count()).toBe(4);
+ expect(rows.get(0).getText()).toBe('Item 3');
+ expect(rows.get(1).getText()).toBe('Item 2');
+
+ button.click();
+
+ expect(rows.count()).toBe(5);
+ expect(rows.get(0).getText()).toBe('Item 4');
+ expect(rows.get(1).getText()).toBe('Item 3');
+ });
+
+ it('should add even class to even entries', function() {
+ var button = element(by.buttonText('Add item'));
+ var rows = element.all(by.repeater('item in items'));
+
+ expect(rows.get(0).getAttribute('class')).not.toMatch(/even/);
+ expect(rows.get(1).getAttribute('class')).toMatch(/even/);
+
+ button.click();
+
+ expect(rows.get(0).getAttribute('class')).not.toMatch(/even/);
+ expect(rows.get(1).getAttribute('class')).toMatch(/even/);
+ });
+
+
*/
var ngClassEvenDirective = classDirective('Even', 1);
@@ -65718,7 +67303,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @restrict AC
*
* @description
- * The `ngCloak` directive is used to prevent the Angular html template from being briefly
+ * The `ngCloak` directive is used to prevent the AngularJS 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.
*
@@ -65737,7 +67322,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* ```
*
* When this css rule is loaded by the browser, all html elements (including their children) that
- * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
+ * are tagged with the `ngCloak` directive are hidden. When AngularJS encounters this directive
* during the compilation of the template it deletes the `ngCloak` element attribute, making
* the compiled element visible.
*
@@ -65802,14 +67387,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* The controller instance can be published into a scope property by specifying
* `ng-controller="as propertyName"`.
*
- * If the current `$controllerProvider` is configured to use globals (via
- * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
- * also be the name of a globally accessible constructor function (deprecated, not recommended).
- *
* @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. Any changes to the data are automatically reflected
+ * easily be called from the AngularJS markup. Any changes to the data are automatically reflected
* in the View without the need for a manual update.
*
* Two different declaration styles are included below:
@@ -65819,7 +67400,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* * one injects `$scope` into the controller:
* `ng-controller="SettingsController2"`
*
- * The second option is more common in the Angular community, and is generally used in boilerplates
+ * The second option is more common in the AngularJS community, and is generally used in boilerplates
* and in this guide. However, there are advantages to binding properties directly to the controller
* and avoiding scope.
*
@@ -66016,31 +67597,31 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
* @element ANY
* @description
*
- * Angular has some features that can conflict with certain restrictions that are applied when using
+ * AngularJS has some features that can conflict with certain restrictions that are applied when using
* [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
*
- * If you intend to implement CSP with these rules then you must tell Angular not to use these
+ * If you intend to implement CSP with these rules then you must tell AngularJS not to use these
* features.
*
* This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
*
*
- * The following default rules in CSP affect Angular:
+ * The following default rules in CSP affect AngularJS:
*
* * The use of `eval()`, `Function(string)` and similar functions to dynamically create and execute
- * code from strings is forbidden. Angular makes use of this in the {@link $parse} service to
- * provide a 30% increase in the speed of evaluating Angular expressions. (This CSP rule can be
+ * code from strings is forbidden. AngularJS makes use of this in the {@link $parse} service to
+ * provide a 30% increase in the speed of evaluating AngularJS expressions. (This CSP rule can be
* disabled with the CSP keyword `unsafe-eval`, but it is generally not recommended as it would
* weaken the protections offered by CSP.)
*
* * The use of inline resources, such as inline `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Your node must be HTTPS in order to connect to it via MyEtherWallet.com. You can [download the MyEtherWallet repo & run it locally](https://github.com/kvhnuke/etherwallet/releases/latest) to connect to your local node. Or, get free SSL certificate via [LetsEncrypt](https://letsencrypt.org/).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PRIVACY POLICY
+
Last updated: August 17, 2018
+
+
INTRODUCTION
+
Welcome to MyEtherWallet, a free, open-source, client-side tool for interacting
+ with the blockchain. MyEtherWallet, Inc. values privacy and we make a
+ concerted effort to minimize and, to the extent possible, eliminate the
+ exposure of personal data during the use of our interface. MyEtherWallet
+ does not collect, hold, or store keys, account information, or passwords.
+ We do not collect data passively, do not monetize the collection of data,
+ and do not use your data for marketing or advertising.
+
+ To the extent we collect any personal information, this privacy policy
+ (“Policy”) describes how MyEtherWallet collects, uses, and shares personal
+ information of people who visit our website (the “Site”), use our mobile
+ application, MEWconnect (the “App”), or otherwise use our services
+ (collectively, the “Services”).
+
+
+ This Policy applies to anyone who accesses the Services. Please read the
+ Policy carefully to understand our practices regarding your information
+ and how we will treat it. By visiting the Site, App, and/or using the
+ Services, you acknowledge that the collection, use, and sharing of your
+ information will take place as described in this Policy.
+
+
+ So that we are clear about the terminology we are using, when we use the
+ phrase “Personal Information” in this Privacy Policy, we mean information
+ about an individual that (either by itself or when combined with information
+ from other available sources) allows that individual to be identified,
+ including, the individual’s name, telephone number, or e-mail address.
+
+
THE BLOCKCHAIN
+
+ Due to the inherent transparency of many blockchains, including the Ethereum
+ Blockchain, transactions that individuals broadcast via MyEtherWallet may
+ be publicly accessible. This includes, but is not limited to, your public
+ sending address, the public address of the receiver, the amount sent or
+ received, and any other data a user has chosen to include in a given
+ transaction. Information stored on a blockchain may be public, immutable,
+ and difficult or even impossible to remove or delete. Transactions and
+ addresses may reveal information about the user’s identity and information
+ can potentially be correlated now or in the future by any party who chooses
+ to do so, including law enforcement. Users are encouraged to review how
+ privacy and transparency on the blockchain works.
+
+
WHAT WE COLLECT
+
+ We collect information about you as described below. We use this
+ information to enhance your experience with our Services.
+
+
Information You Provide
+
+ We may collect Personal Information you choose to provide to us. For
+ example, when you contact us for support through the Services, you give
+ us with your e-mail address and any other information that you choose to
+ provide. Also, if you participate in a MyEtherWallet offer, give-away, or
+ promotion (“Promotion”), you provide your name, e-mail address, and
+ mailing address.
+
+
California Do Not Track Disclosures
+
+ MyEtherWallet does not track users over time and across third party
+ websites to provide targeted advertising and therefore does not respond
+ to Do Not Track (DNT) signals.
+
+
USE OF INFORMATION
+
+ We use the information that we have about you to provide support and certain Services to you.
+
+
+ We may use the Personal Information we collect from and about you to (1)
+ provide you with information or services that you request from us,
+ including to respond to your comments, questions, and/or provide customer
+ service; (2) monitor and analyze usage and trends and personalize and
+ improve the Services and your experience using the Services; and (3)
+ for any other purpose with your consent.
+
+
SHARING OF PERSONAL INFORMATION
+
+ We will not disclose your Personal Information other than as described
+ below, and we do not and will not sell your Personal Information to anyone.
+
+
+ We may share the Personal Information we collect from and about you (1)
+ to fulfill the purpose for which you provided it; (2) with your consent;
+ (3) for legal, protection, and safety purposes; (4) to comply with any
+ court order, law, or legal process, including to respond to any government
+ or regulatory request; (5) to protect the rights of MyEtherWallet, our
+ agents, customers, and others, including by enforcing our agreements,
+ policies, and terms of service; and (6) with those who need it to do work
+ for us (our Service Providers, as defined below).
+
+
Service providers
+
+ We may contract with third parties to perform functions related to the
+ Services (“Service Providers”). In general, Service Providers will have
+ access to your Personal Information only to the extent needed to perform
+ their business functions but may not use or share that personal
+ information for purposes outside the scope of their functions related to
+ the Services.
+
+
LINKS TO OTHER SITES
+
+ The Services contain links to other third-party websites or applications.
+ Once you click on such a link and leave the Site or are redirected to a
+ third-party website or application, you are no longer governed by this
+ Policy. Any information you provide on those sites is subject to that
+ third party’s privacy policy and we are not responsible for the privacy
+ and security practices and policies of those third-party sites or
+ applications.
+
+
OUR COMMITMENT TOWARDS CHILDREN'S PRIVACY
+
+ We do not direct the Services to, nor do we knowingly collect any Personal
+ Information from children under 13. Children under 13 are not eligible to
+ use the Services. If we learn that someone using our Services is under 13
+ years of age, we will take steps to remove any Personal Information from
+ our database and to prevent them from utilizing the Services.
+
+
SECURITY OF YOUR PERSONAL INFORMATION & RIGHTS
+
+ We are committed to protecting the security of Personal Information. We
+ have taken certain physical, administrative, and technical steps to help
+ safeguard the information we collect from and about you. While we take
+ steps to help ensure the integrity and security of our network and
+ systems, we cannot guarantee our security measures.
+
+
In certain circumstances, you will also have the following rights:
+
+
+ Right to access: the right to request certain information about, access
+ to and copies of any Personal Information about you that we are holding
+ (please note that you are entitled to request one copy of the Personal
+ Information that we hold about you at no cost, but for any further copies,
+ we reserve the right to charge a reasonable fee based on administration
+ costs);
+
+
+ Right to rectification: the right to have your Personal Information
+ rectified if it is inaccurate or incomplete;
+
+
+ Right to erasure/“right to be forgotten”: where the processing of your
+ information is based on your consent, the right to withdraw that consent
+ and the right to request that we delete or erase your Personal
+ Information from our systems (however, this will not apply if we are
+ required to hold on to the information for compliance with any legal
+ obligation, or if we require the information to establish or defend any
+ legal claim);
+
+
+ Right to restriction of use of your information: the right to stop us
+ from using your Personal Information or limit the way in which we can
+ use it;
+
+
+ Right to data portability: the right to request that we return any
+ information you have provided in a structured, commonly used, and
+ machine-readable format, or that we send it directly to another company,
+ where technically feasible; and
+
+
+ Right to object: the right to object to our use of your Personal
+ Information including where we use it for our legitimate interests.
+
The following legal bases apply to the ways in which we use and share an individual’s Personal Information:
+
+
+ We rely on an individual’s consent to process Personal Information to
+ provide support and/or carry out Promotions. This consent can be
+ withdrawn at any time.
+
+
+ We also process the information provided by an individual in our
+ legitimate interests in ensuring our business is conducted legitimately
+ and to a high standard.
+
+
+
RETENTION
+
+ We will retain the information you provide in order to process your
+ request, provide support, and/or carry out and fulfill our Promotions. If
+ you request support, we will retain your information for no longer than
+ six (6) months. If you participate in a Promotion, we will retain your
+ information until the Promotion is carried out and ninety (90) days after
+ any prize, reward, or offer is fulfilled. Your Personal Information will
+ then be deleted.
+
+
CONTACT INFORMATION
+
+ We welcome your comments or questions about this Policy. You may contact us at privacy@myetherwallet.com
+
+
CHANGES TO PRIVACY POLICY
+
+ We may modify this Policy from time to time. If we make any changes, we
+ will change the Last Updated date above. We also may provide additional
+ notice, as applicable, depending on the type of change. If you object to
+ any changes, you may stop using the Services. Your continued use of the
+ Services after we publish or otherwise provide notice about our changes
+ to the Policy means that you are consenting to the updated Policy.
+
+
+
+
+
+
+ MyEtherWallet.com does not hold your keys for you. We cannot access accounts, recover keys, reset passwords, nor reverse transactions. Protect your keys & always check that you are on correct URL.
+
+ You are responsible for your security.
+
+
Always backup your keys: MyEtherWallet.com & MyEtherWallet CX are not "web wallets". You do not create an account or give us your funds to hold onto. No data leaves your computer / your browser. We make it easy for you to create, save, and access your information and interact with the blockchain.
+
+
We are not responsible for any loss: Ethereum, MyEtherWallet.com & MyEtherWallet CX, and some of the underlying Javascript libraries we use are under active development. While we have thoroughly tested & tens of thousands of wallets have been successfully created by people all over the globe, there is always the possibility something unexpected happens that causes your funds to be lost. Please do not invest more than you are willing to lose, and please be careful.
+
+
Translations of MyEtherWallet: The community has done an amazing job translating MyEtherWallet into a variety of languages. However, MyEtherWallet can only verify the validity and accuracy of the information provided in English and, because of this, the English version of our website is the official text.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ It looks like you didn't finish reading through these slides last time. ProTip: Finish reading through the slides 😉
+
+
+
+
+
+ Welcome to MyEtherWallet.com
+
+
+
+ We know this click-through shit is annoying. We are sorry.
+
+
+
+
+
+
+ Please take some time to understand this for your own safety. 🙏
+
+
+ Your funds will be stolen if you do not head these warnings.
+
+
+
+ We cannot recover your funds or freeze your account if you visit a phishing site or lose your private key.
+
+
+ What is MEW?
+
+
+
+ MyEtherWallet is a free, open-source, client-side interface.
+
+
+ We allow you to interact directly with the blockchain while remaining in full control of your keys & your funds.
+
+
+ **You** and **only you** are responsible for your security.
+
+ When you open an account with a bank or exchange, they create an account for you in their system.
+
+
+ They keep track of your personal information, account passwords, balances, transactions and ultimately your money.
+
+
+ They charge fees to manage your account and provide services, like refunding transactions when your card gets stolen.
+
+
+ You can write a check or charge your debit card to send money, go online to check your balance, reset your password, and get a new debit card if you lose it.
+
+
+ You have an account *with the bank* and they decide how much money you can send, where you can send it, and how long to hold on a suspicious deposit. All for a fee.
+
+ The blockchain is like a huge, global, decentralized spreadsheet.
+
+
+ It keeps track of who sent how many coins to whom, and what the balance of every account is.
+
+
+ It is stored and maintained by thousands of people (miners) across the globe who have special computers.
+
+
+ It is made up of all the individual transactions sent from MyEtherWallet, MetaMask, Exodus, Mist, Geth, Parity, and everywhere else.
+
+
+ When you see your balance on MyEtherWallet.com or view your transactions on [etherscan.io](https://etherscan.io), you are seeing data on the blockchain, not in our personal systems.
+
+ Because we need you to understand that we **cannot**...
+
+
+
+ Access your account or send your funds for you.
+
+
+ Recover or change your private key.
+
+
+ Recover or reset your password.
+
+
+ Reverse, cancel, or refund transactions.
+
+
+ Freeze accounts.
+
+
+
+ **You** and **only you** are responsible for your security.
+
+
+
+ Be diligent to keep your private key and password safe. Your private key is sometimes called your mnemonic phrase, keystore file, UTC file, JSON file, wallet file.
+
+
+ If lose your private key or password, no one can recover it.
+
+
+ If you enter your private key on a phishing website, you will have **all your funds taken**.
+
+ If MyEtherWallet can't do those things, what's the point?
+
+
+
+
+
+
+
+
+ Because that is the point of decentralization and the blockchain.
+
+
+ You don't have to rely on your bank, government, or anyone else when you want to move your funds.
+
+
+ You don't have to rely on the security of an exchange or bank to keep your funds safe.
+
+
+ If you don't find these things valuable, ask yourself why you think the blockchain and cryptocurrencies are valuable. 😉
+
+
+ If you don't like the sound of this, consider using [Coinbase](https://www.coinbase.com/) or [Blockchain.info](https://blockchain.info/wallet/#/signup). They have more familiar accounts with usernames & passwords.
+
+
+ If you are scared but want to use MEW, [get a hardware wallet](https://myetherwallet.github.io/knowledge-base/hardware-wallets/hardware-wallet-recommendations.html)! These keep your keys secure.
+
+ Phishers send you a message with a link to a website that looks just like MyEtherWallet, EtherDelta, Paypal, or your bank, but is not the real website. They steal your information and then steal your money.
+
+
+
+
+
+ Install [EAL](https://chrome.google.com/webstore/detail/etheraddresslookup/pdknmigbbbhmllnmgdfalmedcmcefdfn) or [MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn) or [Cryptonite by Metacert](https://chrome.google.com/webstore/detail/cryptonite-by-metacert/keghdcpemohlojlglbiegihkljkgnige) or the [MyEtherWallet Chrome Extension](https://chrome.google.com/webstore/detail/myetherwallet-cx/nlbmnnijcnlegkjjpcfjclmcfggfefdm) to block malicious websites.
+
+
+ Always check the URL: `https://www.myetherwallet.com`.
+
+
+ Always make sure the URL bar has `MYETHERWALLET Inc` in green.
+
+
+ Do not trust messages or links sent to you randomly via email, Slack, Reddit, Twitter, etc.
+
+
+ Always navigate directly to a site before you enter information. Do not enter information after clicking a link from a message or email.
+
+
+ [Install an AdBlocker](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en) and do not click ads on your search engine (e.g. Google).
+
+ People will try to get you to give them money in return for nothing.
+
+
+
+
+
+
+ If it is too good to be true, it probably is.
+
+
+ Research before sending money to someone or some project. Look for information on a variety of websites and forums. Be wary.
+
+
+ Ask questions when you don't understand something or it doesn't seem right.
+
+
+ Don't let fear, FUD, or FOMO win over common sense. If something is very urgent, ask yourself 'why?'. It may be to create FOMO or prevent you from doing research.
+
+ If you lose your private key or password, it is gone forever. Don't lose it.
+
+
+
+
+
+ Make a backup of your private key and password. Do NOT just store it on your computer. Print it out on a piece of paper or save it to a USB drive.
+
+
+ Store this paper or USB drive in a different physical location. A backup is not useful if it is destroyed by a fire or flood along with your laptop.
+
+
+ Do not store your private key in Dropbox, Google Drive, or other cloud storage. If that account is compromised, your funds will be stolen.
+
+
+ If you have more than 1-week's worth of pay worth of cryptocurrency, get a hardware wallet. No excuses. It's worth it. I promise.
+
+
+
+
+
+
+
+
+
+ [Even more Security Tips!](https://myetherwallet.github.io/knowledge-base/getting-started/protecting-yourself-and-your-funds.html)
+