diff --git a/app/scripts/controllers/decryptWalletCtrl.js b/app/scripts/controllers/decryptWalletCtrl.js
index c4c10eeaca..a8836789fa 100644
--- a/app/scripts/controllers/decryptWalletCtrl.js
+++ b/app/scripts/controllers/decryptWalletCtrl.js
@@ -627,28 +627,22 @@ var decryptWalletCtrl = function($scope, $sce, walletService) {
globalFuncs.MEWconnectStatus.update(0);
var app = new MewConnectEth();
- $scope.mewConnect = MewConnect.init();
-
- Reflect.defineProperty(MewConnect, "instance", {
- value: $scope.mewConnect
- });
+ globalFuncs.MEWconnectStatus.MEWconnect = MewConnect.init();
$scope.$on("$destroy", function() {
globalFuncs.MEWconnectStatus.newTabOpenedTrigger(false);
globalFuncs.MEWconnectStatus.update(0);
- $scope.mewConnect.disconnectRTC();
- if (MewConnect.instance) {
- Reflect.deleteProperty(MewConnect, "instance");
- }
+ globalFuncs.MEWconnectStatus.MEWconnect.disconnectRTC();
+ globalFuncs.MEWconnectStatus.MEWconnect = null;
});
- $scope.mewConnect.on("codeDisplay", codeDisplay);
- $scope.mewConnect.on("RtcConnectedEvent", rtcConnected);
- $scope.mewConnect.on("RtcClosedEvent", rtcClosed);
- $scope.mewConnect.on("RtcDisconnectEvent", rtcDisconnected);
- $scope.mewConnect.on("address", makeWallet);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("codeDisplay", codeDisplay);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcConnectedEvent", rtcConnected);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcClosedEvent", rtcClosed);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcDisconnectEvent", rtcDisconnected);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("address", makeWallet);
- app.setMewConnect($scope.mewConnect);
+ app.setMewConnect(globalFuncs.MEWconnectStatus.MEWconnect);
app.signalerConnect();
$scope.connectionCodeTimeout = null;
@@ -661,7 +655,7 @@ var decryptWalletCtrl = function($scope, $sce, walletService) {
if ($scope.mewConnectionStatus !== 2) {
$scope.connectionCodeTimeout = null;
uiFuncs.notifier.info("Connected Via MEWconnect");
- $scope.mewConnect.sendRtcMessage("address", "");
+ globalFuncs.MEWconnectStatus.MEWconnect.sendRtcMessage("address", "");
$scope.mewConnectionStatus = 2;
}
}
@@ -709,7 +703,7 @@ var decryptWalletCtrl = function($scope, $sce, walletService) {
};
$scope.mewConnectDisconnect = function() {
- $scope.mewConnect.disconnectRTC();
+ globalFuncs.MEWconnectStatus.MEWconnect.disconnectRTC();
};
//= ================ Mew Connect (end)==============================
$scope.getLedgerPath = function() {
diff --git a/app/scripts/controllers/signMsgCtrl.js b/app/scripts/controllers/signMsgCtrl.js
index b8cbbcdb86..5d5da42099 100644
--- a/app/scripts/controllers/signMsgCtrl.js
+++ b/app/scripts/controllers/signMsgCtrl.js
@@ -202,7 +202,7 @@ var signMsgCtrl = function($scope, $sce, walletService) {
//TODO reset ui when rtc disconnects
// var msg = Buffer.from(thisMessage).toString("hex");
var connectApp = new MewConnectEth();
- var mewConnect = MewConnect.instance;
+ var mewConnect =globalFuncs.MEWconnectStatus.MEWconnect;
connectApp.setMewConnect(mewConnect);
mewConnect.on("signMessage", function(data) {
$scope.signMsg.signedMsg = JSON.stringify(
diff --git a/app/scripts/globalFuncs.js b/app/scripts/globalFuncs.js
index aa19946049..30095a93bb 100644
--- a/app/scripts/globalFuncs.js
+++ b/app/scripts/globalFuncs.js
@@ -394,6 +394,7 @@ globalFuncs.localStorage = {
};
globalFuncs.MEWconnectStatus = {
+ MEWconnect: null,
decryptOpenTriggers: [],
mewConnectListener: function() {},
register: function(listener) {
diff --git a/app/scripts/kyber.js b/app/scripts/kyber.js
index 80a1bd341c..89c50d58df 100644
--- a/app/scripts/kyber.js
+++ b/app/scripts/kyber.js
@@ -420,7 +420,7 @@ kyberFuncs.prototype.getTradeData = function (swapOrder, minRate) {
var funcABI = _this.kyberNetworkABI.trade
var srcTokenAddress = _this.getTokenAddress(swapOrder.fromCoin)
var destTokenAddress = _this.getTokenAddress(swapOrder.toCoin)
- let walletId = '0xDECAF9CD2367cdbb726E904cD6397eDFcAe6068D'
+ let walletId = '0x4247951c2eb6d0bA38d233fe7d542c8c80c9d46A'
let minConversionRate = _this.convertToTokenWei(minRate, 'ETH') // Uses slippagePrice with fallback to MarketRate. 1 => Market Rate, but we could also set this as the quoted rate
let srcAmount = _this.convertToTokenWei(swapOrder.fromVal, swapOrder.fromCoin) //etherUnits.toWei(swapOrder.fromVal, "ether");
let maxDestAmount = 2 ** 200 //100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; // Really big number (like a googol)
diff --git a/app/scripts/staticJS/mewConnectEth.js b/app/scripts/staticJS/mewConnectEth.js
index 3809ef4d33..2f9f4ef1e3 100644
--- a/app/scripts/staticJS/mewConnectEth.js
+++ b/app/scripts/staticJS/mewConnectEth.js
@@ -118,7 +118,7 @@ class MewConnectEth {
static checkBrowser() {
const browser = window.browser;
- const version = browser.version.split(0, 1)[0]
+ const version = browser.version.split('.')[0];
/*
* Chrome > 23
* Firefox > 22
@@ -134,7 +134,7 @@ class MewConnectEth {
// if (+version >= 12) {
// return MewConnectEth.buildBrowserResult(false, '', '');
// } else if (+version === 11) {
- return MewConnectEth.buildBrowserResult(true, 'Safari', 'version: ' + browser.version);
+ return MewConnectEth.buildBrowserResult(true, 'Safari', 'version: ' + browser.version);
// }
} else if (browser.name === 'ie') {
return MewConnectEth.buildBrowserResult(true, 'Internet Explorer', '', true);
@@ -163,8 +163,8 @@ class MewConnectEth {
} else {
return MewConnectEth.buildBrowserResult(false, '', '');
}
- } catch(e) {
- console.error(e)
+ } catch (e) {
+ console.error(e);
}
}
}
diff --git a/app/scripts/uiFuncs.js b/app/scripts/uiFuncs.js
index b07089cf6d..87cbd974ad 100644
--- a/app/scripts/uiFuncs.js
+++ b/app/scripts/uiFuncs.js
@@ -143,8 +143,8 @@ uiFuncs.signTxMewConnect = function (eTx, rawTx, txData, callback) {
// uiFuncs.notifier.info("Tap a touch button on your device to confirm signing.");
var app = new MewConnectEth()
- var mewConnect = MewConnect.instance
-
+ // var mewConnect = MewConnect.instance
+ var mewConnect = globalFuncs.MEWconnectStatus.MEWconnect;
app.setMewConnect(mewConnect)
mewConnect.once('signTx', function(data) {
uiFuncs.notifier.info("The transaction was signed but not sent. Click the blue 'Send Transaction' button to continue.")
diff --git a/chrome-extension/js/etherwallet-master.js b/chrome-extension/js/etherwallet-master.js
index 370f9fcc5a..c3c9f99e4c 100644
--- a/chrome-extension/js/etherwallet-master.js
+++ b/chrome-extension/js/etherwallet-master.js
@@ -1011,8 +1011,6 @@ bity.post = function (path, data, callback) {
module.exports = bity;
},{}],27:[function(require,module,exports){
-"use strict";
-
var darklist = function darklist() {
return [{
address: "0xF193a9aFb00715AaCF7ca9Ebffafe02C77517C2E",
@@ -5311,28 +5309,22 @@ var decryptWalletCtrl = function decryptWalletCtrl($scope, $sce, walletService)
globalFuncs.MEWconnectStatus.update(0);
var app = new MewConnectEth();
- $scope.mewConnect = MewConnect.init();
-
- Reflect.defineProperty(MewConnect, "instance", {
- value: $scope.mewConnect
- });
+ globalFuncs.MEWconnectStatus.MEWconnect = MewConnect.init();
$scope.$on("$destroy", function () {
globalFuncs.MEWconnectStatus.newTabOpenedTrigger(false);
globalFuncs.MEWconnectStatus.update(0);
- $scope.mewConnect.disconnectRTC();
- if (MewConnect.instance) {
- Reflect.deleteProperty(MewConnect, "instance");
- }
+ globalFuncs.MEWconnectStatus.MEWconnect.disconnectRTC();
+ globalFuncs.MEWconnectStatus.MEWconnect = null;
});
- $scope.mewConnect.on("codeDisplay", codeDisplay);
- $scope.mewConnect.on("RtcConnectedEvent", rtcConnected);
- $scope.mewConnect.on("RtcClosedEvent", rtcClosed);
- $scope.mewConnect.on("RtcDisconnectEvent", rtcDisconnected);
- $scope.mewConnect.on("address", makeWallet);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("codeDisplay", codeDisplay);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcConnectedEvent", rtcConnected);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcClosedEvent", rtcClosed);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("RtcDisconnectEvent", rtcDisconnected);
+ globalFuncs.MEWconnectStatus.MEWconnect.on("address", makeWallet);
- app.setMewConnect($scope.mewConnect);
+ app.setMewConnect(globalFuncs.MEWconnectStatus.MEWconnect);
app.signalerConnect();
$scope.connectionCodeTimeout = null;
@@ -5345,7 +5337,7 @@ var decryptWalletCtrl = function decryptWalletCtrl($scope, $sce, walletService)
if ($scope.mewConnectionStatus !== 2) {
$scope.connectionCodeTimeout = null;
uiFuncs.notifier.info("Connected Via MEWconnect");
- $scope.mewConnect.sendRtcMessage("address", "");
+ globalFuncs.MEWconnectStatus.MEWconnect.sendRtcMessage("address", "");
$scope.mewConnectionStatus = 2;
}
}
@@ -5393,7 +5385,7 @@ var decryptWalletCtrl = function decryptWalletCtrl($scope, $sce, walletService)
};
$scope.mewConnectDisconnect = function () {
- $scope.mewConnect.disconnectRTC();
+ globalFuncs.MEWconnectStatus.MEWconnect.disconnectRTC();
};
//= ================ Mew Connect (end)==============================
$scope.getLedgerPath = function () {
@@ -7153,7 +7145,7 @@ var signMsgCtrl = function signMsgCtrl($scope, $sce, walletService) {
//TODO reset ui when rtc disconnects
// var msg = Buffer.from(thisMessage).toString("hex");
var connectApp = new MewConnectEth();
- var mewConnect = MewConnect.instance;
+ var mewConnect = globalFuncs.MEWconnectStatus.MEWconnect;
connectApp.setMewConnect(mewConnect);
mewConnect.on("signMessage", function (data) {
$scope.signMsg.signedMsg = JSON.stringify({
@@ -7234,7 +7226,7 @@ var signMsgCtrl = function signMsgCtrl($scope, $sce, walletService) {
module.exports = signMsgCtrl;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"u2f-api":999}],44:[function(require,module,exports){
+},{"buffer":262,"u2f-api":847}],44:[function(require,module,exports){
'use strict';
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
@@ -9348,8 +9340,6 @@ var walletGenCtrl = function walletGenCtrl($scope) {
module.exports = walletGenCtrl;
},{}],51:[function(require,module,exports){
-'use strict';
-
// For token sale holders:
// 1. Add the address users are sending to
// 2. Add the gas limit users should use to send successfully (this avoids OOG errors)
@@ -10105,8 +10095,6 @@ var walletDecryptDrtv = function walletDecryptDrtv() {
module.exports = walletDecryptDrtv;
},{"./walletDecryptDrtv.html":60}],62:[function(require,module,exports){
-'use strict';
-
var ens = require('./ens');
var domainsaleInterface = require('./domainsaleConfigs/domainsaleABI.json');
@@ -10688,8 +10676,6 @@ module.exports=[
},{}],64:[function(require,module,exports){
(function (Buffer){
-'use strict';
-
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var uts46 = require('idna-uts46');
@@ -11088,7 +11074,7 @@ ens.prototype.checkDomain = function () {
module.exports = ens;
}).call(this,require("buffer").Buffer)
-},{"./ensConfigs/ETHConfig.json":65,"./ensConfigs/ROPConfig.json":66,"./ensConfigs/RinkebyConfig.json":67,"./ensConfigs/auctionABI.json":68,"./ensConfigs/deedABI.json":69,"./ensConfigs/registryABI.json":70,"./ensConfigs/resolverABI.json":71,"./ensConfigs/subDomainABI.json":72,"buffer":414,"idna-uts46":892}],65:[function(require,module,exports){
+},{"./ensConfigs/ETHConfig.json":65,"./ensConfigs/ROPConfig.json":66,"./ensConfigs/RinkebyConfig.json":67,"./ensConfigs/auctionABI.json":68,"./ensConfigs/deedABI.json":69,"./ensConfigs/registryABI.json":70,"./ensConfigs/resolverABI.json":71,"./ensConfigs/subDomainABI.json":72,"buffer":262,"idna-uts46":740}],65:[function(require,module,exports){
module.exports={
"public": {
"resolver": "0x1da022710dF5002339274AaDEe8D58218e9D6AB5",
@@ -13020,6 +13006,7 @@ globalFuncs.localStorage = {
};
globalFuncs.MEWconnectStatus = {
+ MEWconnect: null,
decryptOpenTriggers: [],
mewConnectListener: function mewConnectListener() {},
register: function register(listener) {
@@ -14233,8 +14220,6 @@ module.exports={
}
},{}],77:[function(require,module,exports){
-'use strict';
-
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var mainKyberNetworkABI = require('./kyberConfig/KyberNetworkABI.json');
@@ -14696,7 +14681,7 @@ kyberFuncs.prototype.getTradeData = function (swapOrder, minRate) {
var funcABI = _this.kyberNetworkABI.trade;
var srcTokenAddress = _this.getTokenAddress(swapOrder.fromCoin);
var destTokenAddress = _this.getTokenAddress(swapOrder.toCoin);
- var walletId = '0xDECAF9CD2367cdbb726E904cD6397eDFcAe6068D';
+ var walletId = '0x4247951c2eb6d0bA38d233fe7d542c8c80c9d46A';
var minConversionRate = _this.convertToTokenWei(minRate, 'ETH'); // Uses slippagePrice with fallback to MarketRate. 1 => Market Rate, but we could also set this as the quoted rate
var srcAmount = _this.convertToTokenWei(swapOrder.fromVal, swapOrder.fromCoin); //etherUnits.toWei(swapOrder.fromVal, "ether");
var maxDestAmount = Math.pow(2, 200); //100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; // Really big number (like a googol)
@@ -16141,7 +16126,7 @@ if (IS_CX) {
app.controller("cxDecryptWalletCtrl", ["$scope", "$sce", "walletService", cxDecryptWalletCtrl]);
}
-},{"./ajaxReq":25,"./bity":26,"./constants/darkListConst":27,"./controllers/CX/addWalletCtrl":28,"./controllers/CX/cxDecryptWalletCtrl":29,"./controllers/CX/mainPopCtrl":30,"./controllers/CX/myWalletsCtrl":31,"./controllers/CX/quickSendCtrl":32,"./controllers/bulkGenCtrl":33,"./controllers/contractsCtrl":34,"./controllers/decryptWalletCtrl":35,"./controllers/domainsaleCtrl":36,"./controllers/ensCtrl":37,"./controllers/footerCtrl":38,"./controllers/helpersCtrl":39,"./controllers/offlineTxCtrl":40,"./controllers/onboardingCtrl":41,"./controllers/sendTxCtrl":42,"./controllers/signMsgCtrl":43,"./controllers/swapCtrl":44,"./controllers/tabsCtrl":45,"./controllers/txStatusCtrl":46,"./controllers/viewCtrl":47,"./controllers/viewWalletCtrl":48,"./controllers/walletBalanceCtrl":49,"./controllers/walletGenCtrl":50,"./customGas.js":51,"./cxFuncs":52,"./directives/QRCodeDrtv":53,"./directives/addressFieldDrtv":54,"./directives/balanceDrtv":56,"./directives/blockiesDrtv":57,"./directives/cxWalletDecryptDrtv":58,"./directives/fileReaderDrtv":59,"./directives/walletDecryptDrtv":61,"./domainsale":62,"./ens":64,"./ethFuncs":73,"./etherUnits":74,"./globalFuncs":75,"./homoglyphs.json":76,"./kyber":77,"./localStoragePolyfill":85,"./myetherwallet":87,"./nodes":95,"./services/globalService":96,"./services/walletService":97,"./solidity/coder":101,"./solidity/utils":112,"./staticJS/customMarked":113,"./staticJS/digitalBitboxEth":114,"./staticJS/digitalBitboxUsb":115,"./staticJS/ledger-eth":116,"./staticJS/ledger3":117,"./staticJS/mewConnectEth":118,"./staticJS/secalotEth":119,"./staticJS/secalotUsb":120,"./tokenlib":121,"./translations/translate.js":167,"./uiFuncs":171,"./validator":172,"./web3Wallet":173,"@myetherwallet/mewconnect-web-client":174,"angular":333,"angular-animate":327,"angular-sanitize":329,"angular-translate":331,"angular-translate-handler-log":330,"babel-polyfill":352,"bignumber.js":369,"bip39":370,"crypto":840,"detect-browser":847,"ethereumjs-tx":871,"ethereumjs-util":872,"hdkey":889,"levenshtein":907,"punycode":410,"scryptsy":951,"similarity":966,"string-format":968,"trezor-connect":982,"unicode/category/Ll":1002,"uuid":1006,"wallet-address-validator":1019,"xss-filters":1021}],87:[function(require,module,exports){
+},{"./ajaxReq":25,"./bity":26,"./constants/darkListConst":27,"./controllers/CX/addWalletCtrl":28,"./controllers/CX/cxDecryptWalletCtrl":29,"./controllers/CX/mainPopCtrl":30,"./controllers/CX/myWalletsCtrl":31,"./controllers/CX/quickSendCtrl":32,"./controllers/bulkGenCtrl":33,"./controllers/contractsCtrl":34,"./controllers/decryptWalletCtrl":35,"./controllers/domainsaleCtrl":36,"./controllers/ensCtrl":37,"./controllers/footerCtrl":38,"./controllers/helpersCtrl":39,"./controllers/offlineTxCtrl":40,"./controllers/onboardingCtrl":41,"./controllers/sendTxCtrl":42,"./controllers/signMsgCtrl":43,"./controllers/swapCtrl":44,"./controllers/tabsCtrl":45,"./controllers/txStatusCtrl":46,"./controllers/viewCtrl":47,"./controllers/viewWalletCtrl":48,"./controllers/walletBalanceCtrl":49,"./controllers/walletGenCtrl":50,"./customGas.js":51,"./cxFuncs":52,"./directives/QRCodeDrtv":53,"./directives/addressFieldDrtv":54,"./directives/balanceDrtv":56,"./directives/blockiesDrtv":57,"./directives/cxWalletDecryptDrtv":58,"./directives/fileReaderDrtv":59,"./directives/walletDecryptDrtv":61,"./domainsale":62,"./ens":64,"./ethFuncs":73,"./etherUnits":74,"./globalFuncs":75,"./homoglyphs.json":76,"./kyber":77,"./localStoragePolyfill":85,"./myetherwallet":87,"./nodes":95,"./services/globalService":96,"./services/walletService":97,"./solidity/coder":101,"./solidity/utils":112,"./staticJS/customMarked":113,"./staticJS/digitalBitboxEth":114,"./staticJS/digitalBitboxUsb":115,"./staticJS/ledger-eth":116,"./staticJS/ledger3":117,"./staticJS/mewConnectEth":118,"./staticJS/secalotEth":119,"./staticJS/secalotUsb":120,"./tokenlib":121,"./translations/translate.js":167,"./uiFuncs":171,"./validator":172,"./web3Wallet":173,"@myetherwallet/mewconnect-web-client":870,"angular":181,"angular-animate":175,"angular-sanitize":177,"angular-translate":179,"angular-translate-handler-log":178,"babel-polyfill":200,"bignumber.js":217,"bip39":218,"crypto":688,"detect-browser":695,"ethereumjs-tx":719,"ethereumjs-util":720,"hdkey":737,"levenshtein":755,"punycode":258,"scryptsy":799,"similarity":814,"string-format":816,"trezor-connect":830,"unicode/category/Ll":850,"uuid":854,"wallet-address-validator":867,"xss-filters":869}],87:[function(require,module,exports){
(function (Buffer){
'use strict';
@@ -16548,7 +16533,7 @@ Wallet.getWalletFromPrivKeyFile = function (strjson, password) {
module.exports = Wallet;
}).call(this,require("buffer").Buffer)
-},{"buffer":414}],88:[function(require,module,exports){
+},{"buffer":262}],88:[function(require,module,exports){
'use strict';
var customNode = function customNode(srvrUrl, port, httpBasicAuthentication) {
@@ -17539,8 +17524,6 @@ var walletService = function walletService() {
module.exports = walletService;
},{}],98:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -17569,8 +17552,6 @@ SolidityTypeAddress.prototype.isType = function (name) {
module.exports = SolidityTypeAddress;
},{"./formatters":104,"./type":109}],99:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -17599,8 +17580,6 @@ SolidityTypeBool.prototype.isType = function (name) {
module.exports = SolidityTypeBool;
},{"./formatters":104,"./type":109}],100:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -17632,8 +17611,6 @@ SolidityTypeBytes.prototype.isType = function (name) {
module.exports = SolidityTypeBytes;
},{"./formatters":104,"./type":109}],101:[function(require,module,exports){
-'use strict';
-
/*
This file is part of web3.js.
@@ -17885,8 +17862,6 @@ var coder = new SolidityCoder([new SolidityTypeAddress(), new SolidityTypeBool()
module.exports = coder;
},{"./address":98,"./bool":99,"./bytes":100,"./dynamicbytes":103,"./formatters":104,"./int":105,"./real":107,"./string":108,"./uint":110,"./ureal":111,"./utils":112}],102:[function(require,module,exports){
-'use strict';
-
/*
This file is part of web3.js.
@@ -17937,9 +17912,7 @@ module.exports = {
defaultAccount: undefined
};
-},{"bignumber.js":369}],103:[function(require,module,exports){
-'use strict';
-
+},{"bignumber.js":217}],103:[function(require,module,exports){
var f = require('./formatters');
var SolidityType = require('./type');
@@ -17962,8 +17935,6 @@ SolidityTypeDynamicBytes.prototype.isDynamicType = function () {
module.exports = SolidityTypeDynamicBytes;
},{"./formatters":104,"./type":109}],104:[function(require,module,exports){
-'use strict';
-
/*
This file is part of web3.js.
@@ -18216,9 +18187,7 @@ module.exports = {
formatOutputAddress: formatOutputAddress
};
-},{"./config":102,"./param":106,"./utils":112,"bignumber.js":369}],105:[function(require,module,exports){
-'use strict';
-
+},{"./config":102,"./param":106,"./utils":112,"bignumber.js":217}],105:[function(require,module,exports){
var f = require('./formatters');
var SolidityType = require('./type');
@@ -18253,8 +18222,6 @@ SolidityTypeInt.prototype.isType = function (name) {
module.exports = SolidityTypeInt;
},{"./formatters":104,"./type":109}],106:[function(require,module,exports){
-'use strict';
-
/*
This file is part of web3.js.
@@ -18406,8 +18373,6 @@ SolidityParam.encodeList = function (params) {
module.exports = SolidityParam;
},{"./utils":112}],107:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -18442,8 +18407,6 @@ SolidityTypeReal.prototype.isType = function (name) {
module.exports = SolidityTypeReal;
},{"./formatters":104,"./type":109}],108:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -18466,8 +18429,6 @@ SolidityTypeString.prototype.isDynamicType = function () {
module.exports = SolidityTypeString;
},{"./formatters":104,"./type":109}],109:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityParam = require('./param');
@@ -18720,8 +18681,6 @@ SolidityType.prototype.decode = function (bytes, offset, name) {
module.exports = SolidityType;
},{"./formatters":104,"./param":106}],110:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -18756,8 +18715,6 @@ SolidityTypeUInt.prototype.isType = function (name) {
module.exports = SolidityTypeUInt;
},{"./formatters":104,"./type":109}],111:[function(require,module,exports){
-'use strict';
-
var f = require('./formatters');
var SolidityType = require('./type');
@@ -18792,8 +18749,6 @@ SolidityTypeUReal.prototype.isType = function (name) {
module.exports = SolidityTypeUReal;
},{"./formatters":104,"./type":109}],112:[function(require,module,exports){
-'use strict';
-
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; };
/*
@@ -19380,7 +19335,7 @@ module.exports = {
isJson: isJson
};
-},{"bignumber.js":369,"ethereumjs-util":872,"utf8":1004}],113:[function(require,module,exports){
+},{"bignumber.js":217,"ethereumjs-util":720,"utf8":852}],113:[function(require,module,exports){
'use strict';
var marked = require('marked');
@@ -19411,7 +19366,7 @@ marked.setOptions({
});
module.exports = marked;
-},{"marked":908}],114:[function(require,module,exports){
+},{"marked":756}],114:[function(require,module,exports){
(function (Buffer){
/**
* (c) 2017 Douglas Bakkum, Shift Devices AG
@@ -19579,7 +19534,7 @@ DigitalBitboxEth.prototype.signMessage = function (path, messageHex, callback) {
module.exports = DigitalBitboxEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"crypto":840,"hdkey":889}],115:[function(require,module,exports){
+},{"buffer":262,"crypto":688,"hdkey":737}],115:[function(require,module,exports){
(function (Buffer){
/**
* (c) 2017 Douglas Bakkum, Shift Devices AG
@@ -19636,7 +19591,7 @@ DigitalBitboxUsb.prototype.exchange = function (msg, callback) {
module.exports = DigitalBitboxUsb;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"u2f-api":999}],116:[function(require,module,exports){
+},{"buffer":262,"u2f-api":847}],116:[function(require,module,exports){
(function (Buffer){
/********************************************************************************
* Ledger Communication toolkit
@@ -19851,7 +19806,7 @@ LedgerEth.prototype.signPersonalMessage_async = function (path, messageHex, call
module.exports = LedgerEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":414}],117:[function(require,module,exports){
+},{"buffer":262}],117:[function(require,module,exports){
(function (Buffer){
/********************************************************************************
* Ledger Communication toolkit
@@ -19925,9 +19880,7 @@ Ledger3.prototype.exchange = function (apduHex, callback) {
module.exports = Ledger3;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"u2f-api":999}],118:[function(require,module,exports){
-'use strict';
-
+},{"buffer":262,"u2f-api":847}],118:[function(require,module,exports){
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -20063,7 +20016,7 @@ var MewConnectEth = function () {
key: 'checkBrowser',
value: function checkBrowser() {
var browser = window.browser;
- var version = browser.version.split(0, 1)[0];
+ var version = browser.version.split('.')[0];
/*
* Chrome > 23
* Firefox > 22
@@ -20390,7 +20343,7 @@ SecalotEth.prototype.signMessage = function (path, message, callback) {
module.exports = SecalotEth;
}).call(this,require("buffer").Buffer)
-},{"buffer":414}],120:[function(require,module,exports){
+},{"buffer":262}],120:[function(require,module,exports){
(function (Buffer){
"use strict";
@@ -20437,7 +20390,7 @@ SecalotUsb.prototype.exchange = function (apduHex, callback) {
module.exports = SecalotUsb;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"u2f-api":999}],121:[function(require,module,exports){
+},{"buffer":262,"u2f-api":847}],121:[function(require,module,exports){
'use strict';
var Token = function Token(contractAddress, userAddress, symbol, decimal, type) {
@@ -31441,8 +31394,8 @@ uiFuncs.signTxMewConnect = function (eTx, rawTx, txData, callback) {
// uiFuncs.notifier.info("Tap a touch button on your device to confirm signing.");
var app = new MewConnectEth();
- var mewConnect = MewConnect.instance;
-
+ // var mewConnect = MewConnect.instance
+ var mewConnect = globalFuncs.MEWconnectStatus.MEWconnect;
app.setMewConnect(mewConnect);
mewConnect.once('signTx', function (data) {
uiFuncs.notifier.info("The transaction was signed but not sent. Click the blue 'Send Transaction' button to continue.");
@@ -31665,7 +31618,7 @@ uiFuncs.notifier = {
module.exports = uiFuncs;
}).call(this,require("buffer").Buffer)
-},{"buffer":414,"u2f-api":999}],172:[function(require,module,exports){
+},{"buffer":262,"u2f-api":847}],172:[function(require,module,exports){
'use strict';
var validator = function validator() {};
@@ -31803,83213 +31756,52183 @@ Web3Wallet.prototype.getV3Filename = function (timestamp) {
module.exports = Web3Wallet;
},{"./myetherwallet.js":87}],174:[function(require,module,exports){
-(function (Buffer){
-'use strict';
-
-function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
+/**
+ * @license AngularJS v1.7.5
+ * (c) 2010-2018 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular) {'use strict';
-var createLogger = _interopDefault(require('logging'));
-var EventEmitter = _interopDefault(require('events'));
-var browserOrNode = require('browser-or-node');
-var detectBrowser = require('detect-browser');
-var eccrypto = _interopDefault(require('eccrypto'));
-var ethUtils = _interopDefault(require('ethereumjs-util'));
-var crypto = _interopDefault(require('crypto'));
-var secp256k1 = _interopDefault(require('secp256k1'));
-var debugLogger = _interopDefault(require('debug'));
-var io = _interopDefault(require('socket.io-client'));
-var SimplePeer = _interopDefault(require('simple-peer'));
+var ELEMENT_NODE = 1;
+var COMMENT_NODE = 8;
-var version = "1.0.9";
+var ADD_CLASS_SUFFIX = '-add';
+var REMOVE_CLASS_SUFFIX = '-remove';
+var EVENT_CLASS_PREFIX = 'ng-';
+var ACTIVE_CLASS_SUFFIX = '-active';
+var PREPARE_CLASS_SUFFIX = '-prepare';
-var version$1 = version;
+var NG_ANIMATE_CLASSNAME = 'ng-animate';
+var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren';
-var stunServers = [{ urls: 'stun:global.stun.twilio.com:3478?transport=udp' }];
+// Detect proper transitionend/animationend event names.
+var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
-var versions = ['0.0.1'];
+// If unprefixed events are not supported but webkit-prefixed are, use the latter.
+// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
+// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
+// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
+// Register both events in case `window.onanimationend` is not supported because of that,
+// do the same for `transitionend` as Safari is likely to exhibit similar behavior.
+// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
+// therefore there is no reason to test anymore for other vendor prefixes:
+// http://caniuse.com/#search=transition
+if ((window.ontransitionend === undefined) && (window.onwebkittransitionend !== undefined)) {
+ CSS_PREFIX = '-webkit-';
+ TRANSITION_PROP = 'WebkitTransition';
+ TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
+} else {
+ TRANSITION_PROP = 'transition';
+ TRANSITIONEND_EVENT = 'transitionend';
+}
-var connectionCodeSchemas = {
- '0.0.1': ['version', 'key', 'connId']
-};
+if ((window.onanimationend === undefined) && (window.onwebkitanimationend !== undefined)) {
+ CSS_PREFIX = '-webkit-';
+ ANIMATION_PROP = 'WebkitAnimation';
+ ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
+} else {
+ ANIMATION_PROP = 'animation';
+ ANIMATIONEND_EVENT = 'animationend';
+}
-var connectionCodeSeparator = '_';
+var DURATION_KEY = 'Duration';
+var PROPERTY_KEY = 'Property';
+var DELAY_KEY = 'Delay';
+var TIMING_KEY = 'TimingFunction';
+var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
+var ANIMATION_PLAYSTATE_KEY = 'PlayState';
+var SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
-var signal = {
- attemptingTurn: 'attemptingTurn',
- turnToken: 'turnToken',
- tryTurn: 'tryTurn',
- connection: 'connection',
- connect: 'connect',
- signature: 'signature',
- offerSignal: 'offerSignal',
- offer: 'offer',
- answerSignal: 'answerSignal',
- answer: 'answer',
- rtcConnected: 'rtcConnected',
- disconnect: 'disconnect',
- handshake: 'handshake',
- confirmation: 'confirmation',
- invalidConnection: 'InvalidConnection',
- confirmationFailedBusy: 'confirmationFailedBusy',
- confirmationFailed: 'confirmationFailed'
-};
+var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
+var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
+var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
+var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
-var rtc = {
- error: 'error',
- connect: 'connect',
- close: 'close',
- data: 'data',
- signal: 'signal'
-};
+var ngMinErr = angular.$$minErr('ng');
+function assertArg(arg, name, reason) {
+ if (!arg) {
+ throw ngMinErr('areq', 'Argument \'{0}\' is {1}', (name || '?'), (reason || 'required'));
+ }
+ return arg;
+}
-var iceConnectionState = {
- new: 'new',
- connecting: 'connecting',
- connected: 'connected',
- disconnected: 'disconnected',
- failed: 'failed',
- closed: 'closed'
-};
+function mergeClasses(a,b) {
+ if (!a && !b) return '';
+ if (!a) return b;
+ if (!b) return a;
+ if (isArray(a)) a = a.join(' ');
+ if (isArray(b)) b = b.join(' ');
+ return a + ' ' + b;
+}
-var stages = {
- initiator: 'initiator',
- receiver: 'receiver'
-};
+function packageStyles(options) {
+ var styles = {};
+ if (options && (options.to || options.from)) {
+ styles.to = options.to;
+ styles.from = options.from;
+ }
+ return styles;
+}
-var lifeCycle = {
- RtcInitiatedEvent: 'RtcInitiatedEvent',
- signatureCheck: 'signatureCheck',
- SocketConnectedEvent: 'SocketConnectedEvent',
- confirmationFailedEvent: 'confirmationFailedEvent',
- confirmationFailedBusyEvent: 'confirmationFailedBusyEvent',
- invalidConnectionEvent: 'invalidConnectionEvent',
- codeDisplay: 'codeDisplay',
- checkNumber: 'checkNumber',
- ConnectionId: 'ConnectionId',
- receiverVersion: 'receiverVersion',
- offerCreated: 'offerCreated',
- sendOffer: 'sendOffer',
- answerReceived: 'answerReceived',
- RtcConnectedEvent: 'RtcConnectedEvent',
- RtcConnectedEmitted: "RtcConnectedEmitted",
- RtcClosedEvent: 'RtcClosedEvent',
- RtcDisconnectEvent: 'RtcDisconnectEvent',
- RtcFailedEvent: 'RtcFailedEvent',
- RtcErrorEvent: 'RtcErrorEvent',
- UsingFallback: 'UsingFallback',
- Failed: 'failed',
- attemptedDisconnectedSend: 'attemptedDisconnectedSend'
-};
+function pendClasses(classes, fix, isPrefix) {
+ var className = '';
+ classes = isArray(classes)
+ ? classes
+ : classes && isString(classes) && classes.length
+ ? classes.split(/\s+/)
+ : [];
+ forEach(classes, function(klass, i) {
+ if (klass && klass.length > 0) {
+ className += (i > 0) ? ' ' : '';
+ className += isPrefix ? fix + klass
+ : klass + fix;
+ }
+ });
+ return className;
+}
-var communicationTypes = {
- address: 'address',
- signMessage: 'signMessage',
- signTx: 'signTx'
-};
+function removeFromArray(arr, val) {
+ var index = arr.indexOf(val);
+ if (val >= 0) {
+ arr.splice(index, 1);
+ }
+}
-var asyncToGenerator = function (fn) {
- return function () {
- var gen = fn.apply(this, arguments);
- return new Promise(function (resolve, reject) {
- function step(key, arg) {
- try {
- var info = gen[key](arg);
- var value = info.value;
- } catch (error) {
- reject(error);
- return;
- }
+function stripCommentsFromElement(element) {
+ if (element instanceof jqLite) {
+ switch (element.length) {
+ case 0:
+ return element;
- if (info.done) {
- resolve(value);
- } else {
- return Promise.resolve(value).then(function (value) {
- step("next", value);
- }, function (err) {
- step("throw", err);
- });
+ case 1:
+ // there is no point of stripping anything if the element
+ // is the only element within the jqLite wrapper.
+ // (it's important that we retain the element instance.)
+ if (element[0].nodeType === ELEMENT_NODE) {
+ return element;
}
- }
+ break;
- return step("next");
- });
- };
-};
+ default:
+ return jqLite(extractElementNode(element));
+ }
+ }
-var classCallCheck = function (instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
+ if (element.nodeType === ELEMENT_NODE) {
+ return jqLite(element);
}
-};
+}
-var createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
+function extractElementNode(element) {
+ if (!element[0]) return element;
+ for (var i = 0; i < element.length; i++) {
+ var elm = element[i];
+ if (elm.nodeType === ELEMENT_NODE) {
+ return elm;
}
}
+}
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
-}();
+function $$addClass($$jqLite, element, className) {
+ forEach(element, function(elm) {
+ $$jqLite.addClass(elm, className);
+ });
+}
-var _extends = Object.assign || function (target) {
- for (var i = 1; i < arguments.length; i++) {
- var source = arguments[i];
+function $$removeClass($$jqLite, element, className) {
+ forEach(element, function(elm) {
+ $$jqLite.removeClass(elm, className);
+ });
+}
- for (var key in source) {
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
+function applyAnimationClassesFactory($$jqLite) {
+ return function(element, options) {
+ if (options.addClass) {
+ $$addClass($$jqLite, element, options.addClass);
+ options.addClass = null;
+ }
+ if (options.removeClass) {
+ $$removeClass($$jqLite, element, options.removeClass);
+ options.removeClass = null;
}
+ };
+}
+
+function prepareAnimationOptions(options) {
+ options = options || {};
+ if (!options.$$prepared) {
+ var domOperation = options.domOperation || noop;
+ options.domOperation = function() {
+ options.$$domOperationFired = true;
+ domOperation();
+ domOperation = noop;
+ };
+ options.$$prepared = true;
}
+ return options;
+}
- return target;
-};
+function applyAnimationStyles(element, options) {
+ applyAnimationFromStyles(element, options);
+ applyAnimationToStyles(element, options);
+}
-var inherits = function (subClass, superClass) {
- if (typeof superClass !== "function" && superClass !== null) {
- throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
+function applyAnimationFromStyles(element, options) {
+ if (options.from) {
+ element.css(options.from);
+ options.from = null;
}
+}
- subClass.prototype = Object.create(superClass && superClass.prototype, {
- constructor: {
- value: subClass,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
-};
-
-var possibleConstructorReturn = function (self, call) {
- if (!self) {
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+function applyAnimationToStyles(element, options) {
+ if (options.to) {
+ element.css(options.to);
+ options.to = null;
}
+}
- return call && (typeof call === "object" || typeof call === "function") ? call : self;
-};
+function mergeAnimationDetails(element, oldAnimation, newAnimation) {
+ var target = oldAnimation.options || {};
+ var newOptions = newAnimation.options || {};
-var toConsumableArray = function (arr) {
- if (Array.isArray(arr)) {
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+ var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
+ var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
+ var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
- return arr2;
- } else {
- return Array.from(arr);
+ if (newOptions.preparationClasses) {
+ target.preparationClasses = concatWithSpace(newOptions.preparationClasses, target.preparationClasses);
+ delete newOptions.preparationClasses;
}
-};
-
-/* eslint-disable no-undef */
-
-var logger = createLogger('MewConnectCommon');
-var MewConnectCommon = function (_EventEmitter) {
- inherits(MewConnectCommon, _EventEmitter);
+ // noop is basically when there is no callback; otherwise something has been set
+ var realDomOperation = target.domOperation !== noop ? target.domOperation : null;
- function MewConnectCommon() {
- classCallCheck(this, MewConnectCommon);
+ extend(target, newOptions);
- var _this = possibleConstructorReturn(this, (MewConnectCommon.__proto__ || Object.getPrototypeOf(MewConnectCommon)).call(this));
+ // TODO(matsko or sreeramu): proper fix is to maintain all animation callback in array and call at last,but now only leave has the callback so no issue with this.
+ if (realDomOperation) {
+ target.domOperation = realDomOperation;
+ }
- _this.isBrowser = browserOrNode.isBrowser;
+ if (classes.addClass) {
+ target.addClass = classes.addClass;
+ } else {
+ target.addClass = null;
+ }
- _this.jsonDetails = {
- stunSrvers: [].concat(toConsumableArray(stunServers)),
- signals: _extends({}, signal),
- stages: _extends({}, stages),
- lifeCycle: _extends({}, lifeCycle),
- rtc: _extends({}, rtc),
- communicationTypes: _extends({}, communicationTypes),
- iceConnectionState: _extends({}, iceConnectionState),
- connectionCodeSeparator: connectionCodeSeparator,
- version: version$1,
- versions: versions,
- connectionCodeSchemas: connectionCodeSchemas
- };
- return _this;
+ if (classes.removeClass) {
+ target.removeClass = classes.removeClass;
+ } else {
+ target.removeClass = null;
}
- createClass(MewConnectCommon, [{
- key: 'isJSON',
- value: function isJSON(arg) {
- try {
- JSON.parse(arg);
- return true;
- } catch (e) {
- return false;
- }
- }
- }], [{
- key: 'getBrowserRTC',
- value: function getBrowserRTC() {
- if (typeof window === 'undefined') return null;
- var wrtc = {
- RTCPeerConnection: window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection,
- RTCSessionDescription: window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription,
- RTCIceCandidate: window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate
- };
- if (!wrtc.RTCPeerConnection) return null;
- return wrtc;
- }
- }, {
- key: 'checkWebRTCAvailable',
- value: function checkWebRTCAvailable() {
- var doesNotHaveWebRTC = MewConnectCommon.getBrowserRTC() == null;
- return !doesNotHaveWebRTC;
- // return false
- }
- }, {
- key: 'checkBrowser',
- value: function checkBrowser() {
- var browser = detectBrowser.detect();
- if (browser === null) {
- browser = { version: { split: function split() {
- return [1];
- } } };
- }
- var browserVersion = browser.version.split(0, 1)[0];
- /*
- * Chrome > 23
- * Firefox > 22
- * Opera > 18
- * Safari > 11 (caveats exist)
- * Edge - none (RTCDataChannel not supported)
- * IE - none
- * */
- if (typeof window !== 'undefined') {
- if (browser.name === 'safari') {
- // eslint-disable-next-line global-require
- require('webrtc-adapter');
- return MewConnectCommon.buildBrowserResult(true, 'Safari', 'version: ' + browser.version);
- }
- if (browser.name === 'ie') {
- return MewConnectCommon.buildBrowserResult(true, 'Internet Explorer', '', true);
- }
- if (browser.name === 'edge') {
- return MewConnectCommon.buildBrowserResult(true, 'Edge', 'version: ' + browser.version, true);
- }
- var name = '';
- var minVersion = 0;
+ oldAnimation.addClass = target.addClass;
+ oldAnimation.removeClass = target.removeClass;
- if (browser.name === 'opera') {
- name = 'Opera';
- minVersion = 18;
- } else if (browser.name === 'firefox') {
- name = 'Firefox';
- minVersion = 22;
- } else if (browser.name === 'chrome') {
- name = 'Chrome';
- minVersion = 23;
- } else {
- return MewConnectCommon.buildBrowserResult(false, '', '', true);
- }
+ return target;
+}
- try {
- if (minVersion >= +browserVersion) {
- return MewConnectCommon.buildBrowserResult(true, name, 'version: ' + browserVersion);
- }
- return MewConnectCommon.buildBrowserResult(false, '', '');
- } catch (e) {
- logger.error(e);
- }
- }
- }
- }, {
- key: 'buildBrowserResult',
- value: function buildBrowserResult(status, browser, browserVersion, noSupport) {
- return {
- status: status,
- browser: browser,
- browserVersion: browserVersion,
- noSupport: noSupport || false
- };
- }
- }]);
- return MewConnectCommon;
-}(EventEmitter);
+function resolveElementClasses(existing, toAdd, toRemove) {
+ var ADD_CLASS = 1;
+ var REMOVE_CLASS = -1;
-var logger$1 = createLogger('MewCrypto');
+ var flags = {};
+ existing = splitClassesToLookup(existing);
-var MewConnectCrypto = function () {
- function MewConnectCrypto() {
- classCallCheck(this, MewConnectCrypto);
- }
+ toAdd = splitClassesToLookup(toAdd);
+ forEach(toAdd, function(value, key) {
+ flags[key] = ADD_CLASS;
+ });
- createClass(MewConnectCrypto, [{
- key: 'setPrivate',
- value: function setPrivate(pvtKey) {
- this.prvt = Buffer.from(pvtKey, 'hex');
- }
- }, {
- key: 'generateMessage',
- value: function generateMessage() {
- return crypto.randomBytes(32).toString('hex');
- }
+ toRemove = splitClassesToLookup(toRemove);
+ forEach(toRemove, function(value, key) {
+ flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
+ });
- // Not for the Address, but generate them for the connection check
+ var classes = {
+ addClass: '',
+ removeClass: ''
+ };
- }, {
- key: 'prepareKey',
- value: function prepareKey() {
- this.prvt = this.generatePrivate();
- this.pub = this.generatePublic(this.prvt);
- return { pub: this.pub, pvt: this.prvt };
- }
- }, {
- key: 'generatePrivate',
- value: function generatePrivate() {
- var privKey = void 0;
- do {
- privKey = crypto.randomBytes(32);
- } while (!secp256k1.privateKeyVerify(privKey));
- return privKey;
- }
- }, {
- key: 'generatePublic',
- value: function generatePublic(privKey) {
- var pvt = Buffer.from(privKey, 'hex');
- this.prvt = pvt;
- return secp256k1.publicKeyCreate(pvt);
+ forEach(flags, function(val, klass) {
+ var prop, allow;
+ if (val === ADD_CLASS) {
+ prop = 'addClass';
+ allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
+ } else if (val === REMOVE_CLASS) {
+ prop = 'removeClass';
+ allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
}
- }, {
- key: 'encrypt',
- value: function encrypt(dataToSend) {
- var publicKeyA = eccrypto.getPublic(this.prvt);
- return new Promise(function (resolve, reject) {
- eccrypto.encrypt(publicKeyA, Buffer.from(dataToSend)).then(function (_initial) {
- resolve(_initial);
- }).catch(function (error) {
- reject(error);
- });
- });
+ if (allow) {
+ if (classes[prop].length) {
+ classes[prop] += ' ';
+ }
+ classes[prop] += klass;
}
- }, {
- key: 'decrypt',
- value: function decrypt(dataToSee) {
- var _this = this;
+ });
- return new Promise(function (resolve, reject) {
- eccrypto.decrypt(_this.prvt, {
- ciphertext: Buffer.from(dataToSee.ciphertext),
- ephemPublicKey: Buffer.from(dataToSee.ephemPublicKey),
- iv: Buffer.from(dataToSee.iv),
- mac: Buffer.from(dataToSee.mac)
- }).then(function (_initial) {
- var result = void 0;
- try {
- if (_this.isJSON(_initial)) {
- var humanRadable = JSON.parse(_initial);
- if (Array.isArray(humanRadable)) {
- result = humanRadable[0];
- } else {
- result = humanRadable;
- }
- } else {
- result = _initial.toString();
- }
- } catch (e) {
- logger$1.error(e);
- }
- resolve(JSON.stringify(result));
- }).catch(function (error) {
- reject(error);
- });
- });
+ function splitClassesToLookup(classes) {
+ if (isString(classes)) {
+ classes = classes.split(' ');
}
- }, {
- key: 'signMessage',
- value: function signMessage(msgToSign) {
- var _this2 = this;
- return new Promise(function (resolve, reject) {
- try {
- var msg = ethUtils.hashPersonalMessage(ethUtils.toBuffer(msgToSign));
- var signed = ethUtils.ecsign(Buffer.from(msg), Buffer.from(_this2.prvt, 'hex'));
- var combined = Buffer.concat([Buffer.from([signed.v]), Buffer.from(signed.r), Buffer.from(signed.s)]);
- var combinedHex = combined.toString('hex');
- resolve(combinedHex);
- } catch (e) {
- reject(e);
- }
- });
- }
- }, {
- key: 'bufferToConnId',
- value: function bufferToConnId(buf) {
- return buf.toString('hex').slice(32);
- }
- }, {
- key: 'isJSON',
- value: function isJSON(arg) {
- try {
- JSON.parse(arg);
- return true;
- } catch (e) {
- return false;
+ var obj = {};
+ forEach(classes, function(klass) {
+ // sometimes the split leaves empty string values
+ // incase extra spaces were applied to the options
+ if (klass.length) {
+ obj[klass] = true;
}
- }
- }], [{
- key: 'create',
- value: function create() {
- return new MewConnectCrypto();
- }
- }]);
- return MewConnectCrypto;
-}();
-
-var debug = debugLogger('MEWconnect:initiator');
-
-var logger$2 = createLogger('MewConnectInitiator');
-
-var MewConnectInitiator = function (_MewConnectCommon) {
- inherits(MewConnectInitiator, _MewConnectCommon);
-
- function MewConnectInitiator() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- classCallCheck(this, MewConnectInitiator);
-
- var _this = possibleConstructorReturn(this, (MewConnectInitiator.__proto__ || Object.getPrototypeOf(MewConnectInitiator)).call(this));
-
- _this.supportedBrowser = MewConnectCommon.checkBrowser();
-
- _this.destroyOnUnload();
- _this.p = null;
- _this.socketConnected = false;
- _this.connected = false;
- _this.tryingTurn = false;
- _this.turnDisabled = false;
- _this.signalUrl = null;
- _this.iceState = '';
- _this.turnServers = [];
+ });
+ return obj;
+ }
- _this.io = options.io || io;
- _this.Peer = options.wrtc || SimplePeer;
- _this.mewCrypto = options.cryptoImpl || MewConnectCrypto.create();
+ return classes;
+}
- _this.signals = _this.jsonDetails.signals;
- _this.rtcEvents = _this.jsonDetails.rtc;
- _this.version = _this.jsonDetails.version;
- _this.versions = _this.jsonDetails.versions;
- _this.lifeCycle = _this.jsonDetails.lifeCycle;
- _this.stunServers = _this.jsonDetails.stunSrvers;
- _this.iceStates = _this.jsonDetails.iceConnectionState;
+function getDomNode(element) {
+ return (element instanceof jqLite) ? element[0] : element;
+}
- // Socket is abandoned. disconnect.
- setTimeout(function () {
- if (_this.socket) {
- _this.socketDisconnect();
- }
- }, 120000);
- return _this;
+function applyGeneratedPreparationClasses($$jqLite, element, event, options) {
+ var classes = '';
+ if (event) {
+ classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
}
+ if (options.addClass) {
+ classes = concatWithSpace(classes, pendClasses(options.addClass, ADD_CLASS_SUFFIX));
+ }
+ if (options.removeClass) {
+ classes = concatWithSpace(classes, pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX));
+ }
+ if (classes.length) {
+ options.preparationClasses = classes;
+ element.addClass(classes);
+ }
+}
- // Factory function to create instance using default supplied libraries
-
+function clearGeneratedClasses(element, options) {
+ if (options.preparationClasses) {
+ element.removeClass(options.preparationClasses);
+ options.preparationClasses = null;
+ }
+ if (options.activeClasses) {
+ element.removeClass(options.activeClasses);
+ options.activeClasses = null;
+ }
+}
- createClass(MewConnectInitiator, [{
- key: 'destroyOnUnload',
+function blockTransitions(node, duration) {
+ // we use a negative delay value since it performs blocking
+ // yet it doesn't kill any existing transitions running on the
+ // same element which makes this safe for class-based animations
+ var value = duration ? '-' + duration + 's' : '';
+ applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
+ return [TRANSITION_DELAY_PROP, value];
+}
+function blockKeyframeAnimations(node, applyBlock) {
+ var value = applyBlock ? 'paused' : '';
+ var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
+ applyInlineStyle(node, [key, value]);
+ return [key, value];
+}
- // Check if a WebRTC connection exists before a window/tab is closed or refreshed
- // Destroy the connection if one exists
- value: function destroyOnUnload() {
- var _this2 = this;
+function applyInlineStyle(node, styleTuple) {
+ var prop = styleTuple[0];
+ var value = styleTuple[1];
+ node.style[prop] = value;
+}
- if (browserOrNode.isBrowser) {
- // eslint-disable-next-line no-undef
- window.onunload = window.onbeforeunload = function () {
- var iceStates = [_this2.iceStates.new, _this2.iceStates.connecting, _this2.iceStates.connected];
- if (!_this2.Peer.destroyed || iceStates.includes(_this2.iceState)) {
- _this2.rtcDestroy();
- }
- };
- }
- }
- }, {
- key: 'getSocketConnectionState',
+function concatWithSpace(a,b) {
+ if (!a) return b;
+ if (!b) return a;
+ return a + ' ' + b;
+}
+var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
+ var queue, cancelFn;
- // Returns a boolean indicating whether the socket connection exists and is active
- value: function getSocketConnectionState() {
- return this.socketConnected;
- }
+ function scheduler(tasks) {
+ // we make a copy since RAFScheduler mutates the state
+ // of the passed in array variable and this would be difficult
+ // to track down on the outside code
+ queue = queue.concat(tasks);
+ nextTick();
+ }
- // Returns a boolean indicating whether the WebRTC connection exists and is active
+ queue = scheduler.queue = [];
- }, {
- key: 'getConnectonState',
- value: function getConnectonState() {
- return this.connected;
- }
+ /* waitUntilQuiet does two things:
+ * 1. It will run the FINAL `fn` value only when an uncanceled RAF has passed through
+ * 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
+ *
+ * The motivation here is that animation code can request more time from the scheduler
+ * before the next wave runs. This allows for certain DOM properties such as classes to
+ * be resolved in time for the next animation to run.
+ */
+ scheduler.waitUntilQuiet = function(fn) {
+ if (cancelFn) cancelFn();
- // can be used to listen to specific events, especially those that pass data
+ cancelFn = $$rAF(function() {
+ cancelFn = null;
+ fn();
+ nextTick();
+ });
+ };
- }, {
- key: 'uiCommunicator',
- value: function uiCommunicator(event, data) {
- this.emit(event, data);
- this.emitStatus(event);
- }
+ return scheduler;
- // special status emitter to allow simple listening of various statuses in one listener
+ function nextTick() {
+ if (!queue.length) return;
- }, {
- key: 'emitStatus',
- value: function emitStatus(event) {
- this.emit('status', event);
+ var items = queue.shift();
+ for (var i = 0; i < items.length; i++) {
+ items[i]();
}
- // Emit/Provide the details used in creating the QR Code
-
- }, {
- key: 'displayCode',
- value: function displayCode(data) {
- debug('handshake', data);
- this.socketKey = data;
- var separator = this.jsonDetails.connectionCodeSeparator;
- var qrCodeString = this.version + separator + data + separator + this.connId;
-
- this.uiCommunicator(this.lifeCycle.codeDisplay, qrCodeString);
- this.uiCommunicator(this.lifeCycle.checkNumber, data);
- this.uiCommunicator(this.lifeCycle.ConnectionId, this.connId);
+ if (!cancelFn) {
+ $$rAF(function() {
+ if (!cancelFn) nextTick();
+ });
}
+ }
+}];
- // ===================== [Start] WebSocket Communication Methods and Handlers ========================
-
- // The initial method called to initiate the exchange that can create a WebRTC connection
+/**
+ * @ngdoc directive
+ * @name ngAnimateChildren
+ * @restrict AE
+ * @element ANY
+ *
+ * @description
+ *
+ * ngAnimateChildren allows you to specify that children of this element should animate even if any
+ * of the children's parents are currently animating. By default, when an element has an active `enter`, `leave`, or `move`
+ * (structural) animation, child elements that also have an active structural animation are not animated.
+ *
+ * Note that even if `ngAnimateChildren` is set, no child animations will run when the parent element is removed from the DOM (`leave` animation).
+ *
+ *
+ * @param {string} ngAnimateChildren If the value is empty, `true` or `on`,
+ * then child animations are allowed. If the value is `false`, child animations are not allowed.
+ *
+ * @example
+ *
+
+
+
+
+
+
+
+ List of items:
+
Item {{item}}
+
+
+
+
+
- }, {
- key: 'regenerateCode',
- value: function () {
- var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
- return regeneratorRuntime.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (!(this.signalUrl === null)) {
- _context.next = 2;
- break;
- }
+ .container.ng-enter,
+ .container.ng-leave {
+ transition: all ease 1.5s;
+ }
- throw Error('regenerateCode called before initial code generation');
+ .container.ng-enter,
+ .container.ng-leave-active {
+ opacity: 0;
+ }
- case 2:
- this.socketDisconnect();
- this.initiatorStart(this.signalUrl);
+ .container.ng-leave,
+ .container.ng-enter-active {
+ opacity: 1;
+ }
- case 4:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
+ .item {
+ background: firebrick;
+ color: #FFF;
+ margin-bottom: 10px;
+ }
- function regenerateCode() {
- return _ref.apply(this, arguments);
+ .item.ng-enter,
+ .item.ng-leave {
+ transition: transform 1.5s ease;
}
- return regenerateCode;
- }()
- }, {
- key: 'useFallback',
- value: function () {
- var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
- return regeneratorRuntime.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- this.socketEmit(this.signals.tryTurn, { connId: this.connId });
+ .item.ng-enter {
+ transform: translateX(50px);
+ }
- case 1:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
+ .item.ng-enter-active {
+ transform: translateX(0);
+ }
+
+
+ angular.module('ngAnimateChildren', ['ngAnimate'])
+ .controller('MainController', function MainController() {
+ this.animateChildren = false;
+ this.enterElement = false;
+ });
+
+
+ */
+var $$AnimateChildrenDirective = ['$interpolate', function($interpolate) {
+ return {
+ link: function(scope, element, attrs) {
+ var val = attrs.ngAnimateChildren;
+ if (isString(val) && val.length === 0) { //empty attribute
+ element.data(NG_ANIMATE_CHILDREN_DATA, true);
+ } else {
+ // Interpolate and set the value, so that it is available to
+ // animations that run right after compilation
+ setData($interpolate(val)(scope));
+ attrs.$observe('ngAnimateChildren', setData);
+ }
- function useFallback() {
- return _ref2.apply(this, arguments);
+ function setData(value) {
+ value = value === 'on' || value === 'true';
+ element.data(NG_ANIMATE_CHILDREN_DATA, value);
}
+ }
+ };
+}];
- return useFallback;
- }()
+/* exported $AnimateCssProvider */
- // Initalize a websocket connection with the signal server
-
- }, {
- key: 'initiatorStart',
- value: function () {
- var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(url) {
- var toSign, options;
- return regeneratorRuntime.wrap(function _callee3$(_context3) {
- while (1) {
- switch (_context3.prev = _context3.next) {
- case 0:
- if (this.signalUrl === null) {
- this.signalUrl = url;
- }
- this.keys = this.mewCrypto.prepareKey();
- toSign = this.mewCrypto.generateMessage();
- _context3.next = 5;
- return this.mewCrypto.signMessage(this.keys.pvt.toString('hex'));
+var ANIMATE_TIMER_KEY = '$$animateCss';
- case 5:
- this.signed = _context3.sent;
+/**
+ * @ngdoc service
+ * @name $animateCss
+ * @kind object
+ *
+ * @description
+ * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes
+ * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT
+ * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or
+ * directives to create more complex animations that can be purely driven using CSS code.
+ *
+ * Note that only browsers that support CSS transitions and/or keyframe animations are capable of
+ * rendering animations triggered via `$animateCss` (bad news for IE9 and lower).
+ *
+ * ## General Use
+ * 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 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.
+ *
+ * The example below shows how we can create a folding animation on an element using `ng-if`:
+ *
+ * ```html
+ *
+ *
+ * This element will go BOOM
+ *
+ *
+ * ```
+ *
+ * Now we create the **JavaScript animation** that will trigger the CSS transition:
+ *
+ * ```js
+ * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element, doneFn) {
+ * var height = element[0].offsetHeight;
+ * return $animateCss(element, {
+ * from: { height:'0px' },
+ * to: { height:height + 'px' },
+ * duration: 1 // one second
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ## More Advanced Uses
+ *
+ * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks
+ * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code.
+ *
+ * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation,
+ * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with
+ * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order
+ * to provide a working animation that will run in CSS.
+ *
+ * The example below showcases a more advanced version of the `.fold-animation` from the example above:
+ *
+ * ```js
+ * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element, doneFn) {
+ * var height = element[0].offsetHeight;
+ * return $animateCss(element, {
+ * addClass: 'red large-text pulse-twice',
+ * easing: 'ease-out',
+ * from: { height:'0px' },
+ * to: { height:height + 'px' },
+ * duration: 1 // one second
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * Since we're adding/removing CSS classes then the CSS transition will also pick those up:
+ *
+ * ```css
+ * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code,
+ * the CSS classes below will be transitioned despite them being defined as regular CSS classes */
+ * .red { background:red; }
+ * .large-text { font-size:20px; }
+ *
+ * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */
+ * .pulse-twice {
+ * animation: 0.5s pulse linear 2;
+ * -webkit-animation: 0.5s pulse linear 2;
+ * }
+ *
+ * @keyframes pulse {
+ * from { transform: scale(0.5); }
+ * to { transform: scale(1.5); }
+ * }
+ *
+ * @-webkit-keyframes pulse {
+ * from { -webkit-transform: scale(0.5); }
+ * to { -webkit-transform: scale(1.5); }
+ * }
+ * ```
+ *
+ * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen.
+ *
+ * ## How the Options are handled
+ *
+ * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation
+ * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline
+ * styles using the `from` and `to` properties.
+ *
+ * ```js
+ * var animator = $animateCss(element, {
+ * from: { background:'red' },
+ * to: { background:'blue' }
+ * });
+ * animator.start();
+ * ```
+ *
+ * ```css
+ * .rotating-animation {
+ * animation:0.5s rotate linear;
+ * -webkit-animation:0.5s rotate linear;
+ * }
+ *
+ * @keyframes rotate {
+ * from { transform: rotate(0deg); }
+ * to { transform: rotate(360deg); }
+ * }
+ *
+ * @-webkit-keyframes rotate {
+ * from { -webkit-transform: rotate(0deg); }
+ * to { -webkit-transform: rotate(360deg); }
+ * }
+ * ```
+ *
+ * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is
+ * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition
+ * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition
+ * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied
+ * and spread across the transition and keyframe animation.
+ *
+ * ## What is returned
+ *
+ * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually
+ * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are
+ * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties:
+ *
+ * ```js
+ * var animator = $animateCss(element, { ... });
+ * ```
+ *
+ * Now what do the contents of our `animator` variable look like:
+ *
+ * ```js
+ * {
+ * // starts the animation
+ * start: Function,
+ *
+ * // ends (aborts) the animation
+ * end: Function
+ * }
+ * ```
+ *
+ * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends.
+ * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and styles may have been
+ * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
+ * and that changing them will not reconfigure the parameters of the animation.
+ *
+ * ### runner.done() vs runner.then()
+ * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
+ * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
+ * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
+ * unless you really need a digest to kick off afterwards.
+ *
+ * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
+ * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code).
+ * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works.
+ *
+ * @param {DOMElement} element the element that will be animated
+ * @param {object} options the animation-related options that will be applied during the animation
+ *
+ * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
+ * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
+ * * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and
+ * `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted.
+ * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
+ * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
+ * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
+ * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
+ * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
+ * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation.
+ * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation.
+ * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0`
+ * is provided then the animation will be skipped entirely.
+ * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is
+ * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value
+ * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same
+ * CSS delay value.
+ * * `stagger` - A numeric time value representing the delay between successively animated elements
+ * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
+ * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a
+ * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
+ * * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occurring on the classes being added and removed.)
+ * * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
+ * the animation is closed. This is useful for when the styles are used purely for the sake of
+ * the animation and do not have a lasting visual effect on the element (e.g. a collapse and open animation).
+ * By default this value is set to `false`.
+ *
+ * @return {object} an object with start and end methods and details about the animation.
+ *
+ * * `start` - The method to start the animation. This will return a `Promise` when called.
+ * * `end` - This method will cancel the animation and remove all applied CSS classes and styles.
+ */
+var ONE_SECOND = 1000;
- this.connId = this.mewCrypto.bufferToConnId(this.keys.pub);
- this.displayCode(this.keys.pvt.toString('hex'));
- this.uiCommunicator(this.lifeCycle.signatureCheck);
- options = {
- query: {
- stage: 'initiator',
- signed: this.signed,
- message: toSign,
- connId: this.connId
- },
- transports: ['websocket', 'polling', 'flashsocket'],
- secure: true
- };
+var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
+var CLOSING_TIME_BUFFER = 1.5;
- this.socketManager = this.io(url, options);
- this.socket = this.socketManager.connect();
- this.initiatorConnect(this.socket);
+var DETECT_CSS_PROPERTIES = {
+ transitionDuration: TRANSITION_DURATION_PROP,
+ transitionDelay: TRANSITION_DELAY_PROP,
+ transitionProperty: TRANSITION_PROP + PROPERTY_KEY,
+ animationDuration: ANIMATION_DURATION_PROP,
+ animationDelay: ANIMATION_DELAY_PROP,
+ animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY
+};
- case 13:
- case 'end':
- return _context3.stop();
- }
- }
- }, _callee3, this);
- }));
+var DETECT_STAGGER_CSS_PROPERTIES = {
+ transitionDuration: TRANSITION_DURATION_PROP,
+ transitionDelay: TRANSITION_DELAY_PROP,
+ animationDuration: ANIMATION_DURATION_PROP,
+ animationDelay: ANIMATION_DELAY_PROP
+};
- function initiatorStart(_x2) {
- return _ref3.apply(this, arguments);
- }
+function getCssKeyframeDurationStyle(duration) {
+ return [ANIMATION_DURATION_PROP, duration + 's'];
+}
- return initiatorStart;
- }()
+function getCssDelayStyle(delay, isKeyframeAnimation) {
+ var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP;
+ return [prop, delay + 's'];
+}
- // ------------- WebSocket Communication Methods and Handlers ------------------------------
+function computeCssStyles($window, element, properties) {
+ var styles = Object.create(null);
+ var detectedStyles = $window.getComputedStyle(element) || {};
+ forEach(properties, function(formalStyleName, actualStyleName) {
+ var val = detectedStyles[formalStyleName];
+ if (val) {
+ var c = val.charAt(0);
- // ----- Wrapper around Socket.IO methods
- // socket.emit wrapper
+ // only numerical-based values have a negative sign or digit as the first value
+ if (c === '-' || c === '+' || c >= 0) {
+ val = parseMaxTime(val);
+ }
- }, {
- key: 'socketEmit',
- value: function socketEmit(signal, data) {
- this.socket.binary(false).emit(signal, data);
+ // by setting this to null in the event that the delay is not set or is set directly as 0
+ // then we can still allow for negative values to be used later on and not mistake this
+ // value for being greater than any other negative value.
+ if (val === 0) {
+ val = null;
+ }
+ styles[actualStyleName] = val;
}
+ });
- // socket.disconnect wrapper
+ return styles;
+}
- }, {
- key: 'socketDisconnect',
- value: function socketDisconnect() {
- this.socket.disconnect();
- this.socketConnected = false;
+function parseMaxTime(str) {
+ var maxValue = 0;
+ var values = str.split(/\s*,\s*/);
+ forEach(values, function(value) {
+ // it's always safe to consider only second values and omit `ms` values since
+ // getComputedStyle will always handle the conversion for us
+ if (value.charAt(value.length - 1) === 's') {
+ value = value.substring(0, value.length - 1);
}
+ value = parseFloat(value) || 0;
+ maxValue = maxValue ? Math.max(value, maxValue) : value;
+ });
+ return maxValue;
+}
- // socket.on listener registration wrapper
+function truthyTimingValue(val) {
+ return val === 0 || val != null;
+}
- }, {
- key: 'socketOn',
- value: function socketOn(signal, func) {
- this.socket.on(signal, func);
- }
+function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
+ var style = TRANSITION_PROP;
+ var value = duration + 's';
+ if (applyOnlyDuration) {
+ style += DURATION_KEY;
+ } else {
+ value += ' linear all';
+ }
+ return [style, value];
+}
- // ----- Setup handlers for communication with the signal server
+// 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.
+// We make use of `isDefined` here since an empty string
+// or null value (which is what getPropertyValue will return
+// for a non-existing style) will still be marked as a valid
+// value for the style (a falsy value implies that the style
+// is to be removed at the end of the animation). If we had a simple
+// "OR" statement then it would not be enough to catch that.
+function registerRestorableStyles(backup, node, properties) {
+ forEach(properties, function(prop) {
+ backup[prop] = isDefined(backup[prop])
+ ? backup[prop]
+ : node.style.getPropertyValue(prop);
+ });
+}
- }, {
- key: 'initiatorConnect',
- value: function initiatorConnect(socket) {
- var _this3 = this;
+var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animateProvider) {
- debug('INITIATOR CONNECT');
- this.uiCommunicator(this.lifeCycle.SocketConnectedEvent);
+ this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$animateCache',
+ '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
+ function($window, $$jqLite, $$AnimateRunner, $timeout, $$animateCache,
+ $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
- this.socket.on(this.signals.connect, function () {
- debug('SOCKET CONNECTED');
- _this3.socketConnected = true;
- });
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
- this.socketOn(this.signals.confirmation, this.sendOffer.bind(this)); // response
- this.socketOn(this.signals.answer, this.recieveAnswer.bind(this));
- this.socketOn(this.signals.confirmationFailedBusy, this.busyFailure.bind(this));
- this.socketOn(this.signals.confirmationFailed, this.confirmationFailure.bind(this));
- this.socketOn(this.signals.invalidConnection, this.invalidFailure.bind(this));
- this.socketOn(this.signals.disconnect, this.socketDisconnectHandler.bind(this));
- this.socketOn(this.signals.attemptingTurn, this.willAttemptTurn.bind(this));
- this.socketOn(this.signals.turnToken, this.beginTurn.bind(this));
- return socket;
- }
+ function computeCachedCssStyles(node, className, cacheKey, allowNoDuration, properties) {
+ var timings = $$animateCache.get(cacheKey);
- // ----- Socket Event handlers
+ if (!timings) {
+ timings = computeCssStyles($window, node, properties);
+ if (timings.animationIterationCount === 'infinite') {
+ timings.animationIterationCount = 1;
+ }
+ }
- // Handle Socket Disconnect Event
+ // 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);
- }, {
- key: 'socketDisconnectHandler',
- value: function socketDisconnectHandler(reason) {
- debug(reason);
- this.socketConnected = false;
+ // 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.
+ $$animateCache.put(cacheKey, timings, hasDuration);
+
+ return timings;
}
- // Handle Socket Attempting Turn informative signal
- // Provide Notice that initial WebRTC connection failed and the fallback method will be used
+ function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
+ var stagger;
+ var staggerCacheKey = 'stagger-' + cacheKey;
- }, {
- key: 'willAttemptTurn',
- value: function willAttemptTurn() {
- this.tryingTurn = true;
- debug('TRY TURN CONNECTION');
- this.uiCommunicator(this.lifeCycle.UsingFallback);
- }
+ // 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 ($$animateCache.count(cacheKey) > 0) {
+ stagger = $$animateCache.get(staggerCacheKey);
- // Handle Socket event to initiate turn connection
- // Handle Receipt of TURN server details, and begin a WebRTC connection attempt using TURN
+ if (!stagger) {
+ var staggerClassName = pendClasses(className, '-stagger');
- }, {
- key: 'beginTurn',
- value: function beginTurn(data) {
- this.tryingTurn = true;
- this.retryViaTurn(data);
- }
+ $$jqLite.addClass(node, staggerClassName);
- // ----- Failure Handlers
+ stagger = computeCssStyles($window, node, properties);
- // Handle Failure due to an attempt to join a connection with two existing endpoints
+ // force the conversion of a null value to zero incase not set
+ stagger.animationDuration = Math.max(stagger.animationDuration, 0);
+ stagger.transitionDuration = Math.max(stagger.transitionDuration, 0);
- }, {
- key: 'busyFailure',
- value: function busyFailure() {
- this.uiCommunicator(this.lifeCycle.Failed, this.lifeCycle.confirmationFailedBusyEvent);
- debug('confirmation Failed: Busy');
+ $$jqLite.removeClass(node, staggerClassName);
+
+ $$animateCache.put(staggerCacheKey, stagger, true);
+ }
+ }
+
+ return stagger || {};
}
- // Handle Failure due to no opposing peer existing
+ var rafWaitQueue = [];
+ function waitUntilQuiet(callback) {
+ rafWaitQueue.push(callback);
+ $$rAFScheduler.waitUntilQuiet(function() {
+ $$animateCache.flush();
- }, {
- key: 'invalidFailure',
- value: function invalidFailure() {
- this.uiCommunicator(this.lifeCycle.Failed, this.lifeCycle.invalidConnectionEvent);
- debug('confirmation Failed: no opposite peer found');
+ // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
+ // PLEASE EXAMINE THE `$$forceReflow` service to understand why.
+ var pageWidth = $$forceReflow();
+
+ // we use a for loop to ensure that if the queue is changed
+ // during this looping then it will consider new requests
+ for (var i = 0; i < rafWaitQueue.length; i++) {
+ rafWaitQueue[i](pageWidth);
+ }
+ rafWaitQueue.length = 0;
+ });
}
- // Handle Failure due to the handshake/ verify details being invalid for the connection ID
+ 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);
+ timings.maxDuration = Math.max(
+ timings.animationDuration * timings.animationIterationCount,
+ timings.transitionDuration);
- }, {
- key: 'confirmationFailure',
- value: function confirmationFailure() {
- this.uiCommunicator(this.lifeCycle.Failed, this.lifeCycle.confirmationFailedEvent);
- debug('confirmation Failed: invalid confirmation');
+ return timings;
}
- // =============== [End] WebSocket Communication Methods and Handlers ========================
+ return function init(element, initialOptions) {
+ // all of the animation functions should create
+ // a copy of the options data, however, if a
+ // parent service has already created a copy then
+ // we should stick to using that
+ var options = initialOptions || {};
+ if (!options.$$prepared) {
+ options = prepareAnimationOptions(copy(options));
+ }
- // ======================== [Start] WebRTC Communication Methods =============================
+ var restoreStyles = {};
+ var node = getDomNode(element);
+ if (!node
+ || !node.parentNode
+ || !$$animateQueue.enabled()) {
+ return closeAndReturnNoopAnimator();
+ }
- // ----- WebRTC Setup Methods
+ var temporaryStyles = [];
+ var classes = element.attr('class');
+ var styles = packageStyles(options);
+ var animationClosed;
+ var animationPaused;
+ var animationCompleted;
+ var runner;
+ var runnerHost;
+ var maxDelay;
+ var maxDelayTime;
+ var maxDuration;
+ var maxDurationTime;
+ var startTime;
+ var events = [];
- // A connection pair exists, create and send WebRTC OFFER
+ if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
+ return closeAndReturnNoopAnimator();
+ }
- }, {
- key: 'sendOffer',
- value: function () {
- var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(data) {
- var plainTextVersion, options;
- return regeneratorRuntime.wrap(function _callee4$(_context4) {
- while (1) {
- switch (_context4.prev = _context4.next) {
- case 0:
- _context4.next = 2;
- return this.mewCrypto.decrypt(data.version);
+ var method = options.event && isArray(options.event)
+ ? options.event.join(' ')
+ : options.event;
- case 2:
- plainTextVersion = _context4.sent;
+ var isStructural = method && options.structural;
+ var structuralClassName = '';
+ var addRemoveClassName = '';
- this.peerVersion = plainTextVersion;
- this.uiCommunicator(this.lifeCycle.receiverVersion, plainTextVersion);
- debug('sendOffer', data);
- options = {
- signalListener: this.initiatorSignalListener,
- webRtcConfig: {
- servers: this.stunServers
- }
- };
+ if (isStructural) {
+ structuralClassName = pendClasses(method, EVENT_CLASS_PREFIX, true);
+ } else if (method) {
+ structuralClassName = method;
+ }
- this.initiatorStartRTC(this.socket, options);
+ if (options.addClass) {
+ addRemoveClassName += pendClasses(options.addClass, ADD_CLASS_SUFFIX);
+ }
- case 8:
- case 'end':
- return _context4.stop();
- }
- }
- }, _callee4, this);
- }));
+ if (options.removeClass) {
+ if (addRemoveClassName.length) {
+ addRemoveClassName += ' ';
+ }
+ addRemoveClassName += pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX);
+ }
- function sendOffer(_x3) {
- return _ref4.apply(this, arguments);
+ // there may be a situation where a structural animation is combined together
+ // with CSS classes that need to resolve before the animation is computed.
+ // However this means that there is no explicit CSS code to block the animation
+ // from happening (by setting 0s none in the class name). If this is the case
+ // we need to apply the classes before the first rAF so we know to continue if
+ // there actually is a detected transition or keyframe animation
+ if (options.applyClassesEarly && addRemoveClassName.length) {
+ applyAnimationClasses(element, options);
}
- return sendOffer;
- }()
- }, {
- key: 'initiatorSignalListener',
- value: function initiatorSignalListener(socket, options) {
- var _this4 = this;
+ var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
+ var fullClassName = classes + ' ' + preparationClasses;
+ var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
+ var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
- return function () {
- var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(data) {
- var encryptedSend;
- return regeneratorRuntime.wrap(function _callee5$(_context5) {
- while (1) {
- switch (_context5.prev = _context5.next) {
- case 0:
- _context5.prev = 0;
+ // there is no way we can trigger an animation if no styles and
+ // no classes are being applied which would then trigger a transition,
+ // unless there a is raw keyframe value that is applied to the element.
+ if (!containsKeyframeAnimation
+ && !hasToStyles
+ && !preparationClasses) {
+ return closeAndReturnNoopAnimator();
+ }
- debug('SIGNAL', JSON.stringify(data));
- _context5.next = 4;
- return _this4.mewCrypto.encrypt(JSON.stringify(data));
+ var stagger, cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
+ if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
+ preparationClasses = null;
+ return closeAndReturnNoopAnimator();
+ }
- case 4:
- encryptedSend = _context5.sent;
+ if (options.stagger > 0) {
+ var staggerVal = parseFloat(options.stagger);
+ stagger = {
+ transitionDelay: staggerVal,
+ animationDelay: staggerVal,
+ transitionDuration: 0,
+ animationDuration: 0
+ };
+ } else {
+ stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
+ }
- _this4.uiCommunicator(_this4.lifeCycle.sendOffer);
- _this4.socketEmit(_this4.signals.offerSignal, {
- data: encryptedSend,
- connId: _this4.connId,
- options: options.servers
- });
- _context5.next = 12;
- break;
+ if (!options.$$skipPreparationClasses) {
+ $$jqLite.addClass(element, preparationClasses);
+ }
- case 9:
- _context5.prev = 9;
- _context5.t0 = _context5['catch'](0);
+ var applyOnlyDuration;
- logger$2.error(_context5.t0);
+ if (options.transitionStyle) {
+ var transitionStyle = [TRANSITION_PROP, options.transitionStyle];
+ applyInlineStyle(node, transitionStyle);
+ temporaryStyles.push(transitionStyle);
+ }
- case 12:
- case 'end':
- return _context5.stop();
- }
- }
- }, _callee5, _this4, [[0, 9]]);
- }));
+ if (options.duration >= 0) {
+ applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
+ var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration);
- return function (_x4) {
- return _ref5.apply(this, arguments);
- };
- }();
- }
+ // we set the duration so that it will be picked up by getComputedStyle later
+ applyInlineStyle(node, durationStyle);
+ temporaryStyles.push(durationStyle);
+ }
- // Handle the WebRTC ANSWER from the opposite (mobile) peer
+ if (options.keyframeStyle) {
+ var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle];
+ applyInlineStyle(node, keyframeStyle);
+ temporaryStyles.push(keyframeStyle);
+ }
- }, {
- key: 'recieveAnswer',
- value: function () {
- var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(data) {
- var plainTextOffer;
- return regeneratorRuntime.wrap(function _callee6$(_context6) {
- while (1) {
- switch (_context6.prev = _context6.next) {
- case 0:
- _context6.prev = 0;
- _context6.next = 3;
- return this.mewCrypto.decrypt(data.data);
+ var itemIndex = stagger
+ ? options.staggerIndex >= 0
+ ? options.staggerIndex
+ : $$animateCache.count(cacheKey)
+ : 0;
- case 3:
- plainTextOffer = _context6.sent;
+ var isFirst = itemIndex === 0;
- this.rtcRecieveAnswer({ data: plainTextOffer });
- _context6.next = 10;
- break;
+ // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
+ // without causing any combination of transitions to kick in. By adding a negative delay value
+ // it forces the setup class' transition to end immediately. We later then remove the negative
+ // transition delay to allow for the transition to naturally do it's thing. The beauty here is
+ // that if there is no transition defined then nothing will happen and this will also allow
+ // other transitions to be stacked on top of each other without any chopping them out.
+ if (isFirst && !options.skipBlocking) {
+ blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
+ }
- case 7:
- _context6.prev = 7;
- _context6.t0 = _context6['catch'](0);
+ var timings = computeTimings(node, fullClassName, cacheKey, !isStructural);
+ var relativeDelay = timings.maxDelay;
+ maxDelay = Math.max(relativeDelay, 0);
+ maxDuration = timings.maxDuration;
- logger$2.error(_context6.t0);
+ var flags = {};
+ flags.hasTransitions = timings.transitionDuration > 0;
+ flags.hasAnimations = timings.animationDuration > 0;
+ flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty === 'all';
+ flags.applyTransitionDuration = hasToStyles && (
+ (flags.hasTransitions && !flags.hasTransitionAll)
+ || (flags.hasAnimations && !flags.hasTransitions));
+ flags.applyAnimationDuration = options.duration && flags.hasAnimations;
+ flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions);
+ flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations;
+ flags.recalculateTimingStyles = addRemoveClassName.length > 0;
- case 10:
- case 'end':
- return _context6.stop();
- }
- }
- }, _callee6, this, [[0, 7]]);
- }));
+ if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
+ maxDuration = options.duration ? parseFloat(options.duration) : maxDuration;
- function recieveAnswer(_x5) {
- return _ref6.apply(this, arguments);
+ if (flags.applyTransitionDuration) {
+ flags.hasTransitions = true;
+ timings.transitionDuration = maxDuration;
+ applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
+ temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration));
+ }
+
+ if (flags.applyAnimationDuration) {
+ flags.hasAnimations = true;
+ timings.animationDuration = maxDuration;
+ temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration));
+ }
}
- return recieveAnswer;
- }()
- }, {
- key: 'rtcRecieveAnswer',
- value: function rtcRecieveAnswer(data) {
- this.uiCommunicator(this.lifeCycle.answerReceived);
- this.p.signal(JSON.parse(data.data));
- }
- }, {
- key: 'initiatorStartRTC',
- value: function initiatorStartRTC(socket, options) {
- var _this5 = this;
+ if (maxDuration === 0 && !flags.recalculateTimingStyles) {
+ return closeAndReturnNoopAnimator();
+ }
- var webRtcConfig = options.webRtcConfig || {};
- var signalListener = this.initiatorSignalListener(socket, webRtcConfig.servers);
- var webRtcServers = webRtcConfig.servers || this.stunServers;
+ var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
- var suppliedOptions = options.webRtcOptions || {};
- var defaultOptions = {
- initiator: true,
- trickle: false,
- iceTransportPolicy: 'relay',
- config: {
- iceServers: webRtcServers
+ if (options.delay != null) {
+ var delayStyle;
+ if (typeof options.delay !== 'boolean') {
+ delayStyle = parseFloat(options.delay);
+ // number in options.delay means we have to recalculate the delay for the closing timeout
+ maxDelay = Math.max(delayStyle, 0);
}
- };
- var simpleOptions = _extends({}, defaultOptions, {
- suppliedOptions: suppliedOptions
- });
- debug('initiatorStartRTC - options: ' + simpleOptions);
- this.uiCommunicator(this.lifeCycle.RtcInitiatedEvent);
- this.p = new this.Peer(simpleOptions);
- this.p.on(this.rtcEvents.error, this.onError.bind(this));
- this.p.on(this.rtcEvents.connect, this.onConnect.bind(this));
- this.p.on(this.rtcEvents.close, this.onClose.bind(this));
- this.p.on(this.rtcEvents.data, this.onData.bind(this));
- this.p.on(this.rtcEvents.signal, signalListener.bind(this));
- this.p._pc.addEventListener('iceconnectionstatechange', function (evt) {
- // eslint-disable-next-line no-undef
- if (typeof jest === 'undefined') {
- // included because target is not defined in jest
- debug('iceConnectionState: ' + evt.target.iceConnectionState);
- if (evt.target.iceConnectionState === 'connected' || evt.target.iceConnectionState === 'completed') {
- if (!_this5.connected) {
- _this5.connected = true;
- _this5.uiCommunicator(_this5.lifeCycle.RtcConnectedEvent);
- }
- }
+ if (flags.applyTransitionDelay) {
+ temporaryStyles.push(getCssDelayStyle(delayStyle));
}
- });
- }
-
- // ----- WebRTC Communication Event Handlers
-
- }, {
- key: 'onConnect',
- value: function onConnect() {
- debug('CONNECT', 'ok');
- this.connected = true;
- this.turnDisabled = true;
- this.socketEmit(this.signals.rtcConnected, this.socketKey);
- this.socketDisconnect();
- this.uiCommunicator(this.lifeCycle.RtcConnectedEvent);
- }
- }, {
- key: 'onData',
- value: function () {
- var _ref7 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(data) {
- var decryptedData, parsed;
- return regeneratorRuntime.wrap(function _callee7$(_context7) {
- while (1) {
- switch (_context7.prev = _context7.next) {
- case 0:
- debug('DATA RECEIVED', data.toString());
- _context7.prev = 1;
- decryptedData = void 0;
- if (!this.isJSON(data)) {
- _context7.next = 9;
- break;
- }
+ if (flags.applyAnimationDelay) {
+ temporaryStyles.push(getCssDelayStyle(delayStyle, true));
+ }
+ }
- _context7.next = 6;
- return this.mewCrypto.decrypt(JSON.parse(data.toString()));
+ // we need to recalculate the delay value since we used a pre-emptive negative
+ // delay value and the delay value is required for the final event checking. This
+ // property will ensure that this will happen after the RAF phase has passed.
+ if (options.duration == null && timings.transitionDuration > 0) {
+ flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst;
+ }
- case 6:
- decryptedData = _context7.sent;
- _context7.next = 12;
- break;
+ maxDelayTime = maxDelay * ONE_SECOND;
+ maxDurationTime = maxDuration * ONE_SECOND;
+ if (!options.skipBlocking) {
+ flags.blockTransition = timings.transitionDuration > 0;
+ flags.blockKeyframeAnimation = timings.animationDuration > 0 &&
+ stagger.animationDelay > 0 &&
+ stagger.animationDuration === 0;
+ }
- case 9:
- _context7.next = 11;
- return this.mewCrypto.decrypt(JSON.parse(data.toString()));
+ if (options.from) {
+ if (options.cleanupStyles) {
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.from));
+ }
+ applyAnimationFromStyles(element, options);
+ }
- case 11:
- decryptedData = _context7.sent;
+ if (flags.blockTransition || flags.blockKeyframeAnimation) {
+ applyBlocking(maxDuration);
+ } else if (!options.skipBlocking) {
+ blockTransitions(node, false);
+ }
- case 12:
- if (this.isJSON(decryptedData)) {
- parsed = JSON.parse(decryptedData);
+ // TODO(matsko): for 1.5 change this code to have an animator object for better debugging
+ return {
+ $$willAnimate: true,
+ end: endFn,
+ start: function() {
+ if (animationClosed) return;
- debug('DECRYPTED DATA RECEIVED', parsed);
- this.emit(parsed.type, parsed.data);
- } else {
- debug('DECRYPTED DATA RECEIVED', decryptedData);
- this.emit(decryptedData.type, decryptedData.data);
- }
- _context7.next = 20;
- break;
+ runnerHost = {
+ end: endFn,
+ cancel: cancelFn,
+ resume: null, //this will be set during the start() phase
+ pause: null
+ };
- case 15:
- _context7.prev = 15;
- _context7.t0 = _context7['catch'](1);
+ runner = new $$AnimateRunner(runnerHost);
- logger$2.error(_context7.t0);
- debug('onData ERROR: data=', data);
- debug('onData ERROR: data.toString()=', data.toString());
+ waitUntilQuiet(start);
- case 20:
- case 'end':
- return _context7.stop();
- }
- }
- }, _callee7, this, [[1, 15]]);
- }));
+ // we don't have access to pause/resume the animation
+ // since it hasn't run yet. AnimateRunner will therefore
+ // set noop functions for resume and pause and they will
+ // later be overridden once the animation is triggered
+ return runner;
+ }
+ };
- function onData(_x6) {
- return _ref7.apply(this, arguments);
+ function endFn() {
+ close();
}
- return onData;
- }()
- }, {
- key: 'onClose',
- value: function onClose(data) {
- debug('WRTC CLOSE', data);
- if (this.connected) {
- this.connected = false;
- this.uiCommunicator(this.lifeCycle.RtcClosedEvent);
- } else {
- this.connected = false;
- }
- }
- }, {
- key: 'onError',
- value: function onError(err) {
- debug(err.code);
- debug('WRTC ERROR');
- debug('error', err);
- if (!this.connected && !this.tryingTurn && !this.turnDisabled) {
- this.useFallback();
- } else {
- this.uiCommunicator(this.lifeCycle.RtcErrorEvent);
+ function cancelFn() {
+ close(true);
}
- }
- // ----- WebRTC Communication Methods
+ function close(rejected) {
+ // if the promise has been called already then we shouldn't close
+ // the animation again
+ if (animationClosed || (animationCompleted && animationPaused)) return;
+ animationClosed = true;
+ animationPaused = false;
- }, {
- key: 'sendRtcMessageClosure',
- value: function sendRtcMessageClosure(type, msg) {
- var _this6 = this;
+ if (preparationClasses && !options.$$skipPreparationClasses) {
+ $$jqLite.removeClass(element, preparationClasses);
+ }
- return function () {
- debug('[SEND RTC MESSAGE Closure] type: ' + type + ', message: ' + msg);
- _this6.rtcSend(JSON.stringify({ type: type, data: msg }));
- };
- }
- }, {
- key: 'sendRtcMessage',
- value: function sendRtcMessage(type, msg) {
- debug('[SEND RTC MESSAGE] type: ' + type + ', message: ' + msg);
- this.rtcSend(JSON.stringify({ type: type, data: msg }));
- }
- }, {
- key: 'disconnectRTCClosure',
- value: function disconnectRTCClosure() {
- var _this7 = this;
+ if (activeClasses) {
+ $$jqLite.removeClass(element, activeClasses);
+ }
- return function () {
- debug('DISCONNECT RTC Closure');
- _this7.uiCommunicator(_this7.lifeCycle.RtcDisconnectEvent);
- _this7.rtcDestroy();
- _this7.instance = null;
- };
- }
- }, {
- key: 'disconnectRTC',
- value: function disconnectRTC() {
- debug('DISCONNECT RTC');
- this.uiCommunicator(this.lifeCycle.RtcDisconnectEvent);
- this.rtcDestroy();
- this.instance = null;
- }
- }, {
- key: 'rtcSend',
- value: function () {
- var _ref8 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(arg) {
- var encryptedSend;
- return regeneratorRuntime.wrap(function _callee8$(_context8) {
- while (1) {
- switch (_context8.prev = _context8.next) {
- case 0:
- if (!(this.p !== null)) {
- _context8.next = 15;
- break;
- }
-
- encryptedSend = void 0;
-
- if (!(typeof arg === 'string')) {
- _context8.next = 8;
- break;
- }
-
- _context8.next = 5;
- return this.mewCrypto.encrypt(arg);
-
- case 5:
- encryptedSend = _context8.sent;
- _context8.next = 11;
- break;
+ blockKeyframeAnimations(node, false);
+ blockTransitions(node, false);
- case 8:
- _context8.next = 10;
- return this.mewCrypto.encrypt(JSON.stringify(arg));
+ forEach(temporaryStyles, function(entry) {
+ // There is only one way to remove inline style properties entirely from elements.
+ // By using `removeProperty` this works, but we need to convert camel-cased CSS
+ // styles down to hyphenated values.
+ node.style[entry[0]] = '';
+ });
- case 10:
- encryptedSend = _context8.sent;
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
- case 11:
- debug('SENDING RTC');
- this.p.send(JSON.stringify(encryptedSend));
- _context8.next = 17;
- break;
+ if (Object.keys(restoreStyles).length) {
+ forEach(restoreStyles, function(value, prop) {
+ if (value) {
+ node.style.setProperty(prop, value);
+ } else {
+ node.style.removeProperty(prop);
+ }
+ });
+ }
- case 15:
- // eslint-disable-next-line
- console.error('Attempted to send when no peer connection is connected');
- this.uiCommunicator(this.lifeCycle.attemptedDisconnectedSend);
+ // the reason why we have this option is to allow a synchronous closing callback
+ // that is fired as SOON as the animation ends (when the CSS is removed) or if
+ // the animation never takes off at all. A good example is a leave animation since
+ // the element must be removed just after the animation is over or else the element
+ // will appear on screen for one animation frame causing an overbearing flicker.
+ if (options.onDone) {
+ options.onDone();
+ }
- case 17:
- case 'end':
- return _context8.stop();
- }
- }
- }, _callee8, this);
- }));
+ if (events && events.length) {
+ // Remove the transitionend / animationend listener(s)
+ element.off(events.join(' '), onAnimationProgress);
+ }
- function rtcSend(_x7) {
- return _ref8.apply(this, arguments);
- }
+ //Cancel the fallback closing timeout and remove the timer data
+ var animationTimerData = element.data(ANIMATE_TIMER_KEY);
+ if (animationTimerData) {
+ $timeout.cancel(animationTimerData[0].timer);
+ element.removeData(ANIMATE_TIMER_KEY);
+ }
- return rtcSend;
- }()
- }, {
- key: 'rtcDestroy',
- value: function rtcDestroy() {
- if (this.p !== null) {
- this.p.destroy();
+ // if the preparation function fails then the promise is not setup
+ if (runner) {
+ runner.complete(!rejected);
+ }
}
- }
-
- // ----- WebRTC Communication TURN Fallback Initiator/Handler
- // Fallback Step if initial webRTC connection attempt fails.
- // Retries setting up the WebRTC connection using TURN
- }, {
- key: 'retryViaTurn',
- value: function retryViaTurn(data) {
- debug('Retrying via TURN');
- var options = {
- signalListener: this.initiatorSignalListener,
- webRtcConfig: {
- servers: data.data
+ function applyBlocking(duration) {
+ if (flags.blockTransition) {
+ blockTransitions(node, duration);
}
- };
- this.initiatorStartRTC(this.socket, options);
- }
- // ======================== [End] WebRTC Communication Methods =============================
+ if (flags.blockKeyframeAnimation) {
+ blockKeyframeAnimations(node, !!duration);
+ }
+ }
- }], [{
- key: 'init',
- value: function init(opts) {
- var options = opts !== null ? opts : {};
- return new MewConnectInitiator(options);
- }
- }, {
- key: 'checkBrowser',
- value: function checkBrowser() {
- return MewConnectCommon.checkBrowser();
- }
- }, {
- key: 'checkWebRTCAvailable',
- value: function checkWebRTCAvailable() {
- return MewConnectCommon.checkWebRTCAvailable();
- }
- }]);
- return MewConnectInitiator;
-}(MewConnectCommon);
+ function closeAndReturnNoopAnimator() {
+ runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: cancelFn
+ });
-// INITIATOR CLIENT
+ // should flush the cache animation
+ waitUntilQuiet(noop);
+ close();
-var index = {
- Crypto: MewConnectCrypto,
- Initiator: MewConnectInitiator
-};
+ return {
+ $$willAnimate: false,
+ start: function() {
+ return runner;
+ },
+ end: endFn
+ };
+ }
-module.exports = index;
+ function onAnimationProgress(event) {
+ event.stopPropagation();
+ var ev = event.originalEvent || event;
-}).call(this,require("buffer").Buffer)
-},{"browser-or-node":183,"buffer":414,"crypto":840,"debug":191,"detect-browser":193,"eccrypto":194,"ethereumjs-util":225,"events":874,"logging":255,"secp256k1":278,"simple-peer":292,"socket.io-client":296,"webrtc-adapter":313}],175:[function(require,module,exports){
-module.exports = after
+ if (ev.target !== node) {
+ // Since TransitionEvent / AnimationEvent bubble up,
+ // we have to ignore events by finished child animations
+ return;
+ }
-function after(count, callback, err_cb) {
- var bail = false
- err_cb = err_cb || noop
- proxy.count = count
+ // we now always use `Date.now()` due to the recent changes with
+ // event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
+ var timeStamp = ev.$manualTimeStamp || Date.now();
- return (count === 0) ? callback() : proxy
+ /* Firefox (or possibly just Gecko) likes to not round values up
+ * when a ms measurement is used for the animation */
+ var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
- function proxy(err, result) {
- if (proxy.count <= 0) {
- throw new Error('after called too many times')
+ /* $manualTimeStamp is a mocked timeStamp value which is set
+ * within browserTrigger(). This is only here so that tests can
+ * mock animations properly. Real events fallback to event.timeStamp,
+ * or, if they don't, then a timeStamp is automatically created for them.
+ * We're checking to see if the timeStamp surpasses the expected delay,
+ * but we're using elapsedTime instead of the timeStamp on the 2nd
+ * pre-condition since animationPauseds sometimes close off early */
+ if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
+ // we set this flag to ensure that if the transition is paused then, when resumed,
+ // the animation will automatically close itself since transitions cannot be paused.
+ animationCompleted = true;
+ close();
}
- --proxy.count
+ }
- // after first error, rest are passed to err_cb
- if (err) {
- bail = true
- callback(err)
- // future error callbacks will go to error handler
- callback = err_cb
- } else if (proxy.count === 0 && !bail) {
- callback(null, result)
+ function start() {
+ if (animationClosed) return;
+ if (!node.parentNode) {
+ close();
+ return;
}
- }
-}
-function noop() {}
+ // even though we only pause keyframe animations here the pause flag
+ // will still happen when transitions are used. Only the transition will
+ // not be paused since that is not possible. If the animation ends when
+ // paused then it will not complete until unpaused or cancelled.
+ var playPause = function(playAnimation) {
+ if (!animationCompleted) {
+ animationPaused = !playAnimation;
+ if (timings.animationDuration) {
+ var value = blockKeyframeAnimations(node, animationPaused);
+ if (animationPaused) {
+ temporaryStyles.push(value);
+ } else {
+ removeFromArray(temporaryStyles, value);
+ }
+ }
+ } else if (animationPaused && playAnimation) {
+ animationPaused = false;
+ close();
+ }
+ };
-},{}],176:[function(require,module,exports){
-/**
- * An abstraction for slicing an arraybuffer even when
- * ArrayBuffer.prototype.slice is not supported
- *
- * @api public
- */
+ // checking the stagger duration prevents an accidentally cascade of the CSS delay style
+ // being inherited from the parent. If the transition duration is zero then we can safely
+ // rely that the delay value is an intentional stagger delay style.
+ var maxStagger = itemIndex > 0
+ && ((timings.transitionDuration && stagger.transitionDuration === 0) ||
+ (timings.animationDuration && stagger.animationDuration === 0))
+ && Math.max(stagger.animationDelay, stagger.transitionDelay);
+ if (maxStagger) {
+ $timeout(triggerAnimationStart,
+ Math.floor(maxStagger * itemIndex * ONE_SECOND),
+ false);
+ } else {
+ triggerAnimationStart();
+ }
-module.exports = function(arraybuffer, start, end) {
- var bytes = arraybuffer.byteLength;
- start = start || 0;
- end = end || bytes;
+ // this will decorate the existing promise runner with pause/resume methods
+ runnerHost.resume = function() {
+ playPause(true);
+ };
- if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
+ runnerHost.pause = function() {
+ playPause(false);
+ };
- if (start < 0) { start += bytes; }
- if (end < 0) { end += bytes; }
- if (end > bytes) { end = bytes; }
+ function triggerAnimationStart() {
+ // just incase a stagger animation kicks in when the animation
+ // itself was cancelled entirely
+ if (animationClosed) return;
- if (start >= bytes || start >= end || bytes === 0) {
- return new ArrayBuffer(0);
- }
+ applyBlocking(false);
- var abv = new Uint8Array(arraybuffer);
- var result = new Uint8Array(end - start);
- for (var i = start, ii = 0; i < end; i++, ii++) {
- result[ii] = abv[i];
- }
- return result.buffer;
-};
+ forEach(temporaryStyles, function(entry) {
+ var key = entry[0];
+ var value = entry[1];
+ node.style[key] = value;
+ });
-},{}],177:[function(require,module,exports){
+ applyAnimationClasses(element, options);
+ $$jqLite.addClass(element, activeClasses);
-/**
- * Expose `Backoff`.
- */
+ if (flags.recalculateTimingStyles) {
+ fullClassName = node.getAttribute('class') + ' ' + preparationClasses;
+ cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
-module.exports = Backoff;
+ timings = computeTimings(node, fullClassName, cacheKey, false);
+ relativeDelay = timings.maxDelay;
+ maxDelay = Math.max(relativeDelay, 0);
+ maxDuration = timings.maxDuration;
-/**
- * Initialize backoff timer with `opts`.
- *
- * - `min` initial timeout in milliseconds [100]
- * - `max` max timeout [10000]
- * - `jitter` [0]
- * - `factor` [2]
- *
- * @param {Object} opts
- * @api public
- */
+ if (maxDuration === 0) {
+ close();
+ return;
+ }
-function Backoff(opts) {
- opts = opts || {};
- this.ms = opts.min || 100;
- this.max = opts.max || 10000;
- this.factor = opts.factor || 2;
- this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
- this.attempts = 0;
-}
+ flags.hasTransitions = timings.transitionDuration > 0;
+ flags.hasAnimations = timings.animationDuration > 0;
+ }
-/**
- * Return the backoff duration.
- *
- * @return {Number}
- * @api public
- */
+ if (flags.applyAnimationDelay) {
+ relativeDelay = typeof options.delay !== 'boolean' && truthyTimingValue(options.delay)
+ ? parseFloat(options.delay)
+ : relativeDelay;
-Backoff.prototype.duration = function(){
- var ms = this.ms * Math.pow(this.factor, this.attempts++);
- if (this.jitter) {
- var rand = Math.random();
- var deviation = Math.floor(rand * this.jitter * ms);
- ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
- }
- return Math.min(ms, this.max) | 0;
-};
+ maxDelay = Math.max(relativeDelay, 0);
+ timings.animationDelay = relativeDelay;
+ delayStyle = getCssDelayStyle(relativeDelay, true);
+ temporaryStyles.push(delayStyle);
+ node.style[delayStyle[0]] = delayStyle[1];
+ }
-/**
- * Reset the number of attempts.
- *
- * @api public
- */
+ maxDelayTime = maxDelay * ONE_SECOND;
+ maxDurationTime = maxDuration * ONE_SECOND;
-Backoff.prototype.reset = function(){
- this.attempts = 0;
-};
+ if (options.easing) {
+ var easeProp, easeVal = options.easing;
+ if (flags.hasTransitions) {
+ easeProp = TRANSITION_PROP + TIMING_KEY;
+ temporaryStyles.push([easeProp, easeVal]);
+ node.style[easeProp] = easeVal;
+ }
+ if (flags.hasAnimations) {
+ easeProp = ANIMATION_PROP + TIMING_KEY;
+ temporaryStyles.push([easeProp, easeVal]);
+ node.style[easeProp] = easeVal;
+ }
+ }
-/**
- * Set the minimum duration
- *
- * @api public
- */
+ if (timings.transitionDuration) {
+ events.push(TRANSITIONEND_EVENT);
+ }
-Backoff.prototype.setMin = function(min){
- this.ms = min;
-};
+ if (timings.animationDuration) {
+ events.push(ANIMATIONEND_EVENT);
+ }
-/**
- * Set the maximum duration
- *
- * @api public
- */
+ startTime = Date.now();
+ var timerTime = maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime;
+ var endTime = startTime + timerTime;
-Backoff.prototype.setMax = function(max){
- this.max = max;
-};
+ var animationsData = element.data(ANIMATE_TIMER_KEY) || [];
+ var setupFallbackTimer = true;
+ if (animationsData.length) {
+ var currentTimerData = animationsData[0];
+ setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
+ if (setupFallbackTimer) {
+ $timeout.cancel(currentTimerData.timer);
+ } else {
+ animationsData.push(close);
+ }
+ }
-/**
- * Set the jitter
- *
- * @api public
- */
+ if (setupFallbackTimer) {
+ var timer = $timeout(onAnimationExpired, timerTime, false);
+ animationsData[0] = {
+ timer: timer,
+ expectedEndTime: endTime
+ };
+ animationsData.push(close);
+ element.data(ANIMATE_TIMER_KEY, animationsData);
+ }
-Backoff.prototype.setJitter = function(jitter){
- this.jitter = jitter;
-};
+ if (events.length) {
+ element.on(events.join(' '), onAnimationProgress);
+ }
+ if (options.to) {
+ if (options.cleanupStyles) {
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
+ }
+ applyAnimationToStyles(element, options);
+ }
+ }
-},{}],178:[function(require,module,exports){
-/*
- * base64-arraybuffer
- * https://github.com/niklasvh/base64-arraybuffer
- *
- * Copyright (c) 2012 Niklas von Hertzen
- * Licensed under the MIT license.
- */
-(function(){
- "use strict";
+ function onAnimationExpired() {
+ var animationsData = element.data(ANIMATE_TIMER_KEY);
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ // this will be false in the event that the element was
+ // removed from the DOM (via a leave animation or something
+ // similar)
+ if (animationsData) {
+ for (var i = 1; i < animationsData.length; i++) {
+ animationsData[i]();
+ }
+ element.removeData(ANIMATE_TIMER_KEY);
+ }
+ }
+ }
+ };
+ }];
+}];
- // Use a lookup table to find the index.
- var lookup = new Uint8Array(256);
- for (var i = 0; i < chars.length; i++) {
- lookup[chars.charCodeAt(i)] = i;
- }
+var $$AnimateCssDriverProvider = ['$$animationProvider', /** @this */ function($$animationProvider) {
+ $$animationProvider.drivers.push('$$animateCssDriver');
- exports.encode = function(arraybuffer) {
- var bytes = new Uint8Array(arraybuffer),
- i, len = bytes.length, base64 = "";
+ var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim';
+ var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor';
- for (i = 0; i < len; i+=3) {
- base64 += chars[bytes[i] >> 2];
- base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
- base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
- base64 += chars[bytes[i + 2] & 63];
- }
+ var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
+ var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
- if ((len % 3) === 2) {
- base64 = base64.substring(0, base64.length - 1) + "=";
- } else if (len % 3 === 1) {
- base64 = base64.substring(0, base64.length - 2) + "==";
- }
+ function isDocumentFragment(node) {
+ return node.parentNode && node.parentNode.nodeType === 11;
+ }
- return base64;
- };
+ this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document',
+ function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) {
- exports.decode = function(base64) {
- var bufferLength = base64.length * 0.75,
- len = base64.length, i, p = 0,
- encoded1, encoded2, encoded3, encoded4;
+ // only browsers that support these properties can render animations
+ if (!$sniffer.animations && !$sniffer.transitions) return noop;
- if (base64[base64.length - 1] === "=") {
- bufferLength--;
- if (base64[base64.length - 2] === "=") {
- bufferLength--;
- }
- }
+ var bodyNode = $document[0].body;
+ var rootNode = getDomNode($rootElement);
- var arraybuffer = new ArrayBuffer(bufferLength),
- bytes = new Uint8Array(arraybuffer);
+ var rootBodyElement = jqLite(
+ // this is to avoid using something that exists outside of the body
+ // we also special case the doc fragment case because our unit test code
+ // appends the $rootElement to the body after the app has been bootstrapped
+ isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
+ );
- for (i = 0; i < len; i+=4) {
- encoded1 = lookup[base64.charCodeAt(i)];
- encoded2 = lookup[base64.charCodeAt(i+1)];
- encoded3 = lookup[base64.charCodeAt(i+2)];
- encoded4 = lookup[base64.charCodeAt(i+3)];
+ return function initDriverFn(animationDetails) {
+ return animationDetails.from && animationDetails.to
+ ? prepareFromToAnchorAnimation(animationDetails.from,
+ animationDetails.to,
+ animationDetails.classes,
+ animationDetails.anchors)
+ : prepareRegularAnimation(animationDetails);
+ };
- bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
- bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
- bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
+ function filterCssClasses(classes) {
+ //remove all the `ng-` stuff
+ return classes.replace(/\bng-\S+\b/g, '');
}
- return arraybuffer;
- };
-})();
+ function getUniqueValues(a, b) {
+ if (isString(a)) a = a.split(' ');
+ if (isString(b)) b = b.split(' ');
+ return a.filter(function(val) {
+ return b.indexOf(val) === -1;
+ }).join(' ');
+ }
-},{}],179:[function(require,module,exports){
-// Reference https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
-// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
-// NOTE: SIGHASH byte ignored AND restricted, truncate before use
+ function prepareAnchoredAnimation(classes, outAnchor, inAnchor) {
+ var clone = jqLite(getDomNode(outAnchor).cloneNode(true));
+ var startingClasses = filterCssClasses(getClassVal(clone));
-var Buffer = require('safe-buffer').Buffer
+ outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
-function check (buffer) {
- if (buffer.length < 8) return false
- if (buffer.length > 72) return false
- if (buffer[0] !== 0x30) return false
- if (buffer[1] !== buffer.length - 2) return false
- if (buffer[2] !== 0x02) return false
+ clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME);
- var lenR = buffer[3]
- if (lenR === 0) return false
- if (5 + lenR >= buffer.length) return false
- if (buffer[4 + lenR] !== 0x02) return false
+ rootBodyElement.append(clone);
- var lenS = buffer[5 + lenR]
- if (lenS === 0) return false
- if ((6 + lenR + lenS) !== buffer.length) return false
+ var animatorIn, animatorOut = prepareOutAnimation();
- if (buffer[4] & 0x80) return false
- if (lenR > 1 && (buffer[4] === 0x00) && !(buffer[5] & 0x80)) return false
+ // the user may not end up using the `out` animation and
+ // only making use of the `in` animation or vice-versa.
+ // In either case we should allow this and not assume the
+ // animation is over unless both animations are not used.
+ if (!animatorOut) {
+ animatorIn = prepareInAnimation();
+ if (!animatorIn) {
+ return end();
+ }
+ }
- if (buffer[lenR + 6] & 0x80) return false
- if (lenS > 1 && (buffer[lenR + 6] === 0x00) && !(buffer[lenR + 7] & 0x80)) return false
- return true
-}
+ var startingAnimator = animatorOut || animatorIn;
-function decode (buffer) {
- if (buffer.length < 8) throw new Error('DER sequence length is too short')
- if (buffer.length > 72) throw new Error('DER sequence length is too long')
- if (buffer[0] !== 0x30) throw new Error('Expected DER sequence')
- if (buffer[1] !== buffer.length - 2) throw new Error('DER sequence length is invalid')
- if (buffer[2] !== 0x02) throw new Error('Expected DER integer')
+ return {
+ start: function() {
+ var runner;
- var lenR = buffer[3]
- if (lenR === 0) throw new Error('R length is zero')
- if (5 + lenR >= buffer.length) throw new Error('R length is too long')
- if (buffer[4 + lenR] !== 0x02) throw new Error('Expected DER integer (2)')
+ var currentAnimation = startingAnimator.start();
+ currentAnimation.done(function() {
+ currentAnimation = null;
+ if (!animatorIn) {
+ animatorIn = prepareInAnimation();
+ if (animatorIn) {
+ currentAnimation = animatorIn.start();
+ currentAnimation.done(function() {
+ currentAnimation = null;
+ end();
+ runner.complete();
+ });
+ return currentAnimation;
+ }
+ }
+ // in the event that there is no `in` animation
+ end();
+ runner.complete();
+ });
- var lenS = buffer[5 + lenR]
- if (lenS === 0) throw new Error('S length is zero')
- if ((6 + lenR + lenS) !== buffer.length) throw new Error('S length is invalid')
+ runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: endFn
+ });
- if (buffer[4] & 0x80) throw new Error('R value is negative')
- if (lenR > 1 && (buffer[4] === 0x00) && !(buffer[5] & 0x80)) throw new Error('R value excessively padded')
+ return runner;
- if (buffer[lenR + 6] & 0x80) throw new Error('S value is negative')
- if (lenS > 1 && (buffer[lenR + 6] === 0x00) && !(buffer[lenR + 7] & 0x80)) throw new Error('S value excessively padded')
+ function endFn() {
+ if (currentAnimation) {
+ currentAnimation.end();
+ }
+ }
+ }
+ };
- // non-BIP66 - extract R, S values
- return {
- r: buffer.slice(4, 4 + lenR),
- s: buffer.slice(6 + lenR)
- }
-}
+ function calculateAnchorStyles(anchor) {
+ var styles = {};
-/*
- * Expects r and s to be positive DER integers.
- *
- * The DER format uses the most significant bit as a sign bit (& 0x80).
- * If the significant bit is set AND the integer is positive, a 0x00 is prepended.
- *
- * Examples:
- *
- * 0 => 0x00
- * 1 => 0x01
- * -1 => 0xff
- * 127 => 0x7f
- * -127 => 0x81
- * 128 => 0x0080
- * -128 => 0x80
- * 255 => 0x00ff
- * -255 => 0xff01
- * 16300 => 0x3fac
- * -16300 => 0xc054
- * 62300 => 0x00f35c
- * -62300 => 0xff0ca4
-*/
-function encode (r, s) {
- var lenR = r.length
- var lenS = s.length
- if (lenR === 0) throw new Error('R length is zero')
- if (lenS === 0) throw new Error('S length is zero')
- if (lenR > 33) throw new Error('R length is too long')
- if (lenS > 33) throw new Error('S length is too long')
- if (r[0] & 0x80) throw new Error('R value is negative')
- if (s[0] & 0x80) throw new Error('S value is negative')
- if (lenR > 1 && (r[0] === 0x00) && !(r[1] & 0x80)) throw new Error('R value excessively padded')
- if (lenS > 1 && (s[0] === 0x00) && !(s[1] & 0x80)) throw new Error('S value excessively padded')
+ var coords = getDomNode(anchor).getBoundingClientRect();
- var signature = Buffer.allocUnsafe(6 + lenR + lenS)
+ // we iterate directly since safari messes up and doesn't return
+ // all the keys for the coords object when iterated
+ forEach(['width','height','top','left'], function(key) {
+ var value = coords[key];
+ switch (key) {
+ case 'top':
+ value += bodyNode.scrollTop;
+ break;
+ case 'left':
+ value += bodyNode.scrollLeft;
+ break;
+ }
+ styles[key] = Math.floor(value) + 'px';
+ });
+ return styles;
+ }
- // 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
- signature[0] = 0x30
- signature[1] = signature.length - 2
- signature[2] = 0x02
- signature[3] = r.length
- r.copy(signature, 4)
- signature[4 + lenR] = 0x02
- signature[5 + lenR] = s.length
- s.copy(signature, 6 + lenR)
+ function prepareOutAnimation() {
+ var animator = $animateCss(clone, {
+ addClass: NG_OUT_ANCHOR_CLASS_NAME,
+ delay: true,
+ from: calculateAnchorStyles(outAnchor)
+ });
- return signature
-}
+ // read the comment within `prepareRegularAnimation` to understand
+ // why this check is necessary
+ return animator.$$willAnimate ? animator : null;
+ }
-module.exports = {
- check: check,
- decode: decode,
- encode: encode
-}
+ function getClassVal(element) {
+ return element.attr('class') || '';
+ }
-},{"safe-buffer":276}],180:[function(require,module,exports){
-(function (global){
-/**
- * Create a blob builder even when vendor prefixes exist
- */
+ function prepareInAnimation() {
+ var endingClasses = filterCssClasses(getClassVal(inAnchor));
+ var toAdd = getUniqueValues(endingClasses, startingClasses);
+ var toRemove = getUniqueValues(startingClasses, endingClasses);
-var BlobBuilder = global.BlobBuilder
- || global.WebKitBlobBuilder
- || global.MSBlobBuilder
- || global.MozBlobBuilder;
+ var animator = $animateCss(clone, {
+ to: calculateAnchorStyles(inAnchor),
+ addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd,
+ removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove,
+ delay: true
+ });
-/**
- * Check if Blob constructor is supported
- */
+ // read the comment within `prepareRegularAnimation` to understand
+ // why this check is necessary
+ return animator.$$willAnimate ? animator : null;
+ }
-var blobSupported = (function() {
- try {
- var a = new Blob(['hi']);
- return a.size === 2;
- } catch(e) {
- return false;
- }
-})();
+ function end() {
+ clone.remove();
+ outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ }
+ }
-/**
- * Check if Blob constructor supports ArrayBufferViews
- * Fails in Safari 6, so we need to map to ArrayBuffers there.
- */
+ function prepareFromToAnchorAnimation(from, to, classes, anchors) {
+ var fromAnimation = prepareRegularAnimation(from, noop);
+ var toAnimation = prepareRegularAnimation(to, noop);
-var blobSupportsArrayBufferView = blobSupported && (function() {
- try {
- var b = new Blob([new Uint8Array([1,2])]);
- return b.size === 2;
- } catch(e) {
- return false;
- }
-})();
+ var anchorAnimations = [];
+ forEach(anchors, function(anchor) {
+ var outElement = anchor['out'];
+ var inElement = anchor['in'];
+ var animator = prepareAnchoredAnimation(classes, outElement, inElement);
+ if (animator) {
+ anchorAnimations.push(animator);
+ }
+ });
-/**
- * Check if BlobBuilder is supported
- */
+ // no point in doing anything when there are no elements to animate
+ if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return;
-var blobBuilderSupported = BlobBuilder
- && BlobBuilder.prototype.append
- && BlobBuilder.prototype.getBlob;
+ return {
+ start: function() {
+ var animationRunners = [];
-/**
- * Helper function that maps ArrayBufferViews to ArrayBuffers
- * Used by BlobBuilder constructor and old browsers that didn't
- * support it in the Blob constructor.
- */
+ if (fromAnimation) {
+ animationRunners.push(fromAnimation.start());
+ }
-function mapArrayBufferViews(ary) {
- for (var i = 0; i < ary.length; i++) {
- var chunk = ary[i];
- if (chunk.buffer instanceof ArrayBuffer) {
- var buf = chunk.buffer;
+ if (toAnimation) {
+ animationRunners.push(toAnimation.start());
+ }
- // if this is a subarray, make a copy so we only
- // include the subarray region from the underlying buffer
- if (chunk.byteLength !== buf.byteLength) {
- var copy = new Uint8Array(chunk.byteLength);
- copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
- buf = copy.buffer;
- }
+ forEach(anchorAnimations, function(animation) {
+ animationRunners.push(animation.start());
+ });
- ary[i] = buf;
- }
- }
-}
+ var runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: endFn // CSS-driven animations cannot be cancelled, only ended
+ });
-function BlobBuilderConstructor(ary, options) {
- options = options || {};
+ $$AnimateRunner.all(animationRunners, function(status) {
+ runner.complete(status);
+ });
- var bb = new BlobBuilder();
- mapArrayBufferViews(ary);
+ return runner;
- for (var i = 0; i < ary.length; i++) {
- bb.append(ary[i]);
- }
+ function endFn() {
+ forEach(animationRunners, function(runner) {
+ runner.end();
+ });
+ }
+ }
+ };
+ }
- return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
-};
+ function prepareRegularAnimation(animationDetails) {
+ var element = animationDetails.element;
+ var options = animationDetails.options || {};
-function BlobConstructor(ary, options) {
- mapArrayBufferViews(ary);
- return new Blob(ary, options || {});
-};
+ if (animationDetails.structural) {
+ options.event = animationDetails.event;
+ options.structural = true;
+ options.applyClassesEarly = true;
-module.exports = (function() {
- if (blobSupported) {
- return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
- } else if (blobBuilderSupported) {
- return BlobBuilderConstructor;
- } else {
- return undefined;
- }
-})();
+ // we special case the leave animation since we want to ensure that
+ // the element is removed as soon as the animation is over. Otherwise
+ // a flicker might appear or the element may not be removed at all
+ if (animationDetails.event === 'leave') {
+ options.onDone = options.domOperation;
+ }
+ }
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],181:[function(require,module,exports){
-(function (module, exports) {
- 'use strict';
+ // We assign the preparationClasses as the actual animation event since
+ // the internals of $animateCss will just suffix the event token values
+ // with `-active` to trigger the animation.
+ if (options.preparationClasses) {
+ options.event = concatWithSpace(options.event, options.preparationClasses);
+ }
- // Utils
- function assert (val, msg) {
- if (!val) throw new Error(msg || 'Assertion failed');
- }
+ var animator = $animateCss(element, options);
- // Could use `inherits` module, but don't want to move from single file
- // architecture yet.
- function inherits (ctor, superCtor) {
- ctor.super_ = superCtor;
- var TempCtor = function () {};
- TempCtor.prototype = superCtor.prototype;
- ctor.prototype = new TempCtor();
- ctor.prototype.constructor = ctor;
- }
+ // the driver lookup code inside of $$animation attempts to spawn a
+ // driver one by one until a driver returns a.$$willAnimate animator object.
+ // $animateCss will always return an object, however, it will pass in
+ // a flag as a hint as to whether an animation was detected or not
+ return animator.$$willAnimate ? animator : null;
+ }
+ }];
+}];
- // BN
+// TODO(matsko): use caching here to speed things up for detection
+// TODO(matsko): add documentation
+// by the time...
- function BN (number, base, endian) {
- if (BN.isBN(number)) {
- return number;
- }
+var $$AnimateJsProvider = ['$animateProvider', /** @this */ function($animateProvider) {
+ this.$get = ['$injector', '$$AnimateRunner', '$$jqLite',
+ function($injector, $$AnimateRunner, $$jqLite) {
- this.negative = 0;
- this.words = null;
- this.length = 0;
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+ // $animateJs(element, 'enter');
+ return function(element, event, classes, options) {
+ var animationClosed = false;
- // Reduction context
- this.red = null;
+ // the `classes` argument is optional and if it is not used
+ // then the classes will be resolved from the element's className
+ // property as well as options.addClass/options.removeClass.
+ if (arguments.length === 3 && isObject(classes)) {
+ options = classes;
+ classes = null;
+ }
- if (number !== null) {
- if (base === 'le' || base === 'be') {
- endian = base;
- base = 10;
+ options = prepareAnimationOptions(options);
+ if (!classes) {
+ classes = element.attr('class') || '';
+ if (options.addClass) {
+ classes += ' ' + options.addClass;
+ }
+ if (options.removeClass) {
+ classes += ' ' + options.removeClass;
+ }
}
- this._init(number || 0, base || 10, endian || 'be');
- }
- }
- if (typeof module === 'object') {
- module.exports = BN;
- } else {
- exports.BN = BN;
- }
+ var classesToAdd = options.addClass;
+ var classesToRemove = options.removeClass;
- BN.BN = BN;
- BN.wordSize = 26;
+ // the lookupAnimations function returns a series of animation objects that are
+ // matched up with one or more of the CSS classes. These animation objects are
+ // defined via the module.animation factory function. If nothing is detected then
+ // we don't return anything which then makes $animation query the next driver.
+ var animations = lookupAnimations(classes);
+ var before, after;
+ if (animations.length) {
+ var afterFn, beforeFn;
+ if (event === 'leave') {
+ beforeFn = 'leave';
+ afterFn = 'afterLeave'; // TODO(matsko): get rid of this
+ } else {
+ beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1);
+ afterFn = event;
+ }
- var Buffer;
- try {
- Buffer = require('buffer').Buffer;
- } catch (e) {
- }
+ if (event !== 'enter' && event !== 'move') {
+ before = packageAnimations(element, event, options, animations, beforeFn);
+ }
+ after = packageAnimations(element, event, options, animations, afterFn);
+ }
- BN.isBN = function isBN (num) {
- if (num instanceof BN) {
- return true;
- }
+ // no matching animations
+ if (!before && !after) return;
- return num !== null && typeof num === 'object' &&
- num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
- };
+ function applyOptions() {
+ options.domOperation();
+ applyAnimationClasses(element, options);
+ }
- BN.max = function max (left, right) {
- if (left.cmp(right) > 0) return left;
- return right;
- };
+ function close() {
+ animationClosed = true;
+ applyOptions();
+ applyAnimationStyles(element, options);
+ }
- BN.min = function min (left, right) {
- if (left.cmp(right) < 0) return left;
- return right;
- };
+ var runner;
- BN.prototype._init = function init (number, base, endian) {
- if (typeof number === 'number') {
- return this._initNumber(number, base, endian);
- }
-
- if (typeof number === 'object') {
- return this._initArray(number, base, endian);
- }
+ return {
+ $$willAnimate: true,
+ end: function() {
+ if (runner) {
+ runner.end();
+ } else {
+ close();
+ runner = new $$AnimateRunner();
+ runner.complete(true);
+ }
+ return runner;
+ },
+ start: function() {
+ if (runner) {
+ return runner;
+ }
- if (base === 'hex') {
- base = 16;
- }
- assert(base === (base | 0) && base >= 2 && base <= 36);
+ runner = new $$AnimateRunner();
+ var closeActiveAnimations;
+ var chain = [];
- number = number.toString().replace(/\s+/g, '');
- var start = 0;
- if (number[0] === '-') {
- start++;
- }
+ if (before) {
+ chain.push(function(fn) {
+ closeActiveAnimations = before(fn);
+ });
+ }
- if (base === 16) {
- this._parseHex(number, start);
- } else {
- this._parseBase(number, base, start);
- }
+ if (chain.length) {
+ chain.push(function(fn) {
+ applyOptions();
+ fn(true);
+ });
+ } else {
+ applyOptions();
+ }
- if (number[0] === '-') {
- this.negative = 1;
- }
+ if (after) {
+ chain.push(function(fn) {
+ closeActiveAnimations = after(fn);
+ });
+ }
- this.strip();
+ runner.setHost({
+ end: function() {
+ endAnimations();
+ },
+ cancel: function() {
+ endAnimations(true);
+ }
+ });
- if (endian !== 'le') return;
+ $$AnimateRunner.chain(chain, onComplete);
+ return runner;
- this._initArray(this.toArray(), base, endian);
- };
+ function onComplete(success) {
+ close(success);
+ runner.complete(success);
+ }
- BN.prototype._initNumber = function _initNumber (number, base, endian) {
- if (number < 0) {
- this.negative = 1;
- number = -number;
- }
- if (number < 0x4000000) {
- this.words = [ number & 0x3ffffff ];
- this.length = 1;
- } else if (number < 0x10000000000000) {
- this.words = [
- number & 0x3ffffff,
- (number / 0x4000000) & 0x3ffffff
- ];
- this.length = 2;
- } else {
- assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
- this.words = [
- number & 0x3ffffff,
- (number / 0x4000000) & 0x3ffffff,
- 1
- ];
- this.length = 3;
- }
+ function endAnimations(cancelled) {
+ if (!animationClosed) {
+ (closeActiveAnimations || noop)(cancelled);
+ onComplete(cancelled);
+ }
+ }
+ }
+ };
- if (endian !== 'le') return;
+ function executeAnimationFn(fn, element, event, options, onDone) {
+ var args;
+ switch (event) {
+ case 'animate':
+ args = [element, options.from, options.to, onDone];
+ break;
- // Reverse the bytes
- this._initArray(this.toArray(), base, endian);
- };
+ case 'setClass':
+ args = [element, classesToAdd, classesToRemove, onDone];
+ break;
- BN.prototype._initArray = function _initArray (number, base, endian) {
- // Perhaps a Uint8Array
- assert(typeof number.length === 'number');
- if (number.length <= 0) {
- this.words = [ 0 ];
- this.length = 1;
- return this;
- }
+ case 'addClass':
+ args = [element, classesToAdd, onDone];
+ break;
- this.length = Math.ceil(number.length / 3);
- this.words = new Array(this.length);
- for (var i = 0; i < this.length; i++) {
- this.words[i] = 0;
- }
+ case 'removeClass':
+ args = [element, classesToRemove, onDone];
+ break;
- var j, w;
- var off = 0;
- if (endian === 'be') {
- for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
- w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
- this.words[j] |= (w << off) & 0x3ffffff;
- this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
- off += 24;
- if (off >= 26) {
- off -= 26;
- j++;
+ default:
+ args = [element, onDone];
+ break;
}
- }
- } else if (endian === 'le') {
- for (i = 0, j = 0; i < number.length; i += 3) {
- w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
- this.words[j] |= (w << off) & 0x3ffffff;
- this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
- off += 24;
- if (off >= 26) {
- off -= 26;
- j++;
+
+ args.push(options);
+
+ var value = fn.apply(fn, args);
+ if (value) {
+ if (isFunction(value.start)) {
+ value = value.start();
+ }
+
+ if (value instanceof $$AnimateRunner) {
+ value.done(onDone);
+ } else if (isFunction(value)) {
+ // optional onEnd / onCancel callback
+ return value;
+ }
}
+
+ return noop;
}
- }
- return this.strip();
- };
- function parseHex (str, start, end) {
- var r = 0;
- var len = Math.min(str.length, end);
- for (var i = start; i < len; i++) {
- var c = str.charCodeAt(i) - 48;
+ function groupEventedAnimations(element, event, options, animations, fnName) {
+ var operations = [];
+ forEach(animations, function(ani) {
+ var animation = ani[fnName];
+ if (!animation) return;
- r <<= 4;
+ // note that all of these animations will run in parallel
+ operations.push(function() {
+ var runner;
+ var endProgressCb;
- // 'a' - 'f'
- if (c >= 49 && c <= 54) {
- r |= c - 49 + 0xa;
+ var resolved = false;
+ var onAnimationComplete = function(rejected) {
+ if (!resolved) {
+ resolved = true;
+ (endProgressCb || noop)(rejected);
+ runner.complete(!rejected);
+ }
+ };
- // 'A' - 'F'
- } else if (c >= 17 && c <= 22) {
- r |= c - 17 + 0xa;
+ runner = new $$AnimateRunner({
+ end: function() {
+ onAnimationComplete();
+ },
+ cancel: function() {
+ onAnimationComplete(true);
+ }
+ });
- // '0' - '9'
- } else {
- r |= c & 0xf;
- }
- }
- return r;
- }
+ endProgressCb = executeAnimationFn(animation, element, event, options, function(result) {
+ var cancelled = result === false;
+ onAnimationComplete(cancelled);
+ });
- BN.prototype._parseHex = function _parseHex (number, start) {
- // Create possibly bigger array to ensure that it fits the number
- this.length = Math.ceil((number.length - start) / 6);
- this.words = new Array(this.length);
- for (var i = 0; i < this.length; i++) {
- this.words[i] = 0;
- }
+ return runner;
+ });
+ });
- var j, w;
- // Scan 24-bit chunks and add them to the number
- var off = 0;
- for (i = number.length - 6, j = 0; i >= start; i -= 6) {
- w = parseHex(number, i, i + 6);
- this.words[j] |= (w << off) & 0x3ffffff;
- // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
- this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
- off += 24;
- if (off >= 26) {
- off -= 26;
- j++;
+ return operations;
}
- }
- if (i + 6 !== start) {
- w = parseHex(number, start, i + 6);
- this.words[j] |= (w << off) & 0x3ffffff;
- this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
- }
- this.strip();
- };
- function parseBase (str, start, end, mul) {
- var r = 0;
- var len = Math.min(str.length, end);
- for (var i = start; i < len; i++) {
- var c = str.charCodeAt(i) - 48;
+ function packageAnimations(element, event, options, animations, fnName) {
+ var operations = groupEventedAnimations(element, event, options, animations, fnName);
+ if (operations.length === 0) {
+ var a, b;
+ if (fnName === 'beforeSetClass') {
+ a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass');
+ b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass');
+ } else if (fnName === 'setClass') {
+ a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass');
+ b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass');
+ }
- r *= mul;
+ if (a) {
+ operations = operations.concat(a);
+ }
+ if (b) {
+ operations = operations.concat(b);
+ }
+ }
- // 'a'
- if (c >= 49) {
- r += c - 49 + 0xa;
+ if (operations.length === 0) return;
- // 'A'
- } else if (c >= 17) {
- r += c - 17 + 0xa;
+ // TODO(matsko): add documentation
+ return function startAnimation(callback) {
+ var runners = [];
+ if (operations.length) {
+ forEach(operations, function(animateFn) {
+ runners.push(animateFn());
+ });
+ }
- // '0' - '9'
- } else {
- r += c;
+ if (runners.length) {
+ $$AnimateRunner.all(runners, callback);
+ } else {
+ callback();
+ }
+
+ return function endFn(reject) {
+ forEach(runners, function(runner) {
+ if (reject) {
+ runner.cancel();
+ } else {
+ runner.end();
+ }
+ });
+ };
+ };
+ }
+ };
+
+ function lookupAnimations(classes) {
+ classes = isArray(classes) ? classes : classes.split(' ');
+ var matches = [], flagMap = {};
+ for (var i = 0; i < classes.length; i++) {
+ var klass = classes[i],
+ animationFactory = $animateProvider.$$registeredAnimations[klass];
+ if (animationFactory && !flagMap[klass]) {
+ matches.push($injector.get(animationFactory));
+ flagMap[klass] = true;
+ }
}
+ return matches;
}
- return r;
- }
+ }];
+}];
- BN.prototype._parseBase = function _parseBase (number, base, start) {
- // Initialize as zero
- this.words = [ 0 ];
- this.length = 1;
+var $$AnimateJsDriverProvider = ['$$animationProvider', /** @this */ function($$animationProvider) {
+ $$animationProvider.drivers.push('$$animateJsDriver');
+ this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) {
+ return function initDriverFn(animationDetails) {
+ if (animationDetails.from && animationDetails.to) {
+ var fromAnimation = prepareAnimation(animationDetails.from);
+ var toAnimation = prepareAnimation(animationDetails.to);
+ if (!fromAnimation && !toAnimation) return;
- // Find length of limb in base
- for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
- limbLen++;
- }
- limbLen--;
- limbPow = (limbPow / base) | 0;
+ return {
+ start: function() {
+ var animationRunners = [];
- var total = number.length - start;
- var mod = total % limbLen;
- var end = Math.min(total, total - mod) + start;
+ if (fromAnimation) {
+ animationRunners.push(fromAnimation.start());
+ }
- var word = 0;
- for (var i = start; i < end; i += limbLen) {
- word = parseBase(number, i, i + limbLen, base);
+ if (toAnimation) {
+ animationRunners.push(toAnimation.start());
+ }
- this.imuln(limbPow);
- if (this.words[0] + word < 0x4000000) {
- this.words[0] += word;
- } else {
- this._iaddn(word);
- }
- }
+ $$AnimateRunner.all(animationRunners, done);
- if (mod !== 0) {
- var pow = 1;
- word = parseBase(number, i, number.length, base);
+ var runner = new $$AnimateRunner({
+ end: endFnFactory(),
+ cancel: endFnFactory()
+ });
- for (i = 0; i < mod; i++) {
- pow *= base;
- }
+ return runner;
- this.imuln(pow);
- if (this.words[0] + word < 0x4000000) {
- this.words[0] += word;
+ function endFnFactory() {
+ return function() {
+ forEach(animationRunners, function(runner) {
+ // at this point we cannot cancel animations for groups just yet. 1.5+
+ runner.end();
+ });
+ };
+ }
+
+ function done(status) {
+ runner.complete(status);
+ }
+ }
+ };
} else {
- this._iaddn(word);
+ return prepareAnimation(animationDetails);
}
- }
- };
+ };
- BN.prototype.copy = function copy (dest) {
- dest.words = new Array(this.length);
- for (var i = 0; i < this.length; i++) {
- dest.words[i] = this.words[i];
+ function prepareAnimation(animationDetails) {
+ // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations
+ var element = animationDetails.element;
+ var event = animationDetails.event;
+ var options = animationDetails.options;
+ var classes = animationDetails.classes;
+ return $$animateJs(element, event, classes, options);
}
- dest.length = this.length;
- dest.negative = this.negative;
- dest.red = this.red;
- };
+ }];
+}];
- BN.prototype.clone = function clone () {
- var r = new BN(null);
- this.copy(r);
- return r;
- };
+var NG_ANIMATE_ATTR_NAME = 'data-ng-animate';
+var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
+var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animateProvider) {
+ var PRE_DIGEST_STATE = 1;
+ var RUNNING_STATE = 2;
+ var ONE_SPACE = ' ';
- BN.prototype._expand = function _expand (size) {
- while (this.length < size) {
- this.words[this.length++] = 0;
- }
- return this;
+ var rules = this.rules = {
+ skip: [],
+ cancel: [],
+ join: []
};
- // Remove leading `0` from `this`
- BN.prototype.strip = function strip () {
- while (this.length > 1 && this.words[this.length - 1] === 0) {
- this.length--;
- }
- return this._normSign();
- };
+ function getEventData(options) {
+ return {
+ addClass: options.addClass,
+ removeClass: options.removeClass,
+ from: options.from,
+ to: options.to
+ };
+ }
- BN.prototype._normSign = function _normSign () {
- // -0 = 0
- if (this.length === 1 && this.words[0] === 0) {
- this.negative = 0;
+ function makeTruthyCssClassMap(classString) {
+ if (!classString) {
+ return null;
}
- return this;
- };
-
- BN.prototype.inspect = function inspect () {
- return (this.red ? '';
- };
-
- /*
- var zeros = [];
- var groupSizes = [];
- var groupBases = [];
+ var keys = classString.split(ONE_SPACE);
+ var map = Object.create(null);
- var s = '';
- var i = -1;
- while (++i < BN.wordSize) {
- zeros[i] = s;
- s += '0';
+ forEach(keys, function(key) {
+ map[key] = true;
+ });
+ return map;
}
- groupSizes[0] = 0;
- groupSizes[1] = 0;
- groupBases[0] = 0;
- groupBases[1] = 0;
- var base = 2 - 1;
- while (++base < 36 + 1) {
- var groupSize = 0;
- var groupBase = 1;
- while (groupBase < (1 << BN.wordSize) / base) {
- groupBase *= base;
- groupSize += 1;
+
+ function hasMatchingClasses(newClassString, currentClassString) {
+ if (newClassString && currentClassString) {
+ var currentClassMap = makeTruthyCssClassMap(currentClassString);
+ return newClassString.split(ONE_SPACE).some(function(className) {
+ return currentClassMap[className];
+ });
}
- groupSizes[base] = groupSize;
- groupBases[base] = groupBase;
}
- */
+ function isAllowed(ruleType, currentAnimation, previousAnimation) {
+ return rules[ruleType].some(function(fn) {
+ return fn(currentAnimation, previousAnimation);
+ });
+ }
- var zeros = [
- '',
- '0',
- '00',
- '000',
- '0000',
- '00000',
- '000000',
- '0000000',
- '00000000',
- '000000000',
- '0000000000',
- '00000000000',
- '000000000000',
- '0000000000000',
- '00000000000000',
- '000000000000000',
- '0000000000000000',
- '00000000000000000',
- '000000000000000000',
- '0000000000000000000',
- '00000000000000000000',
- '000000000000000000000',
- '0000000000000000000000',
- '00000000000000000000000',
- '000000000000000000000000',
- '0000000000000000000000000'
- ];
+ function hasAnimationClasses(animation, and) {
+ var a = (animation.addClass || '').length > 0;
+ var b = (animation.removeClass || '').length > 0;
+ return and ? a && b : a || b;
+ }
- var groupSizes = [
- 0, 0,
- 25, 16, 12, 11, 10, 9, 8,
- 8, 7, 7, 7, 7, 6, 6,
- 6, 6, 6, 6, 6, 5, 5,
- 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5
- ];
+ rules.join.push(function(newAnimation, currentAnimation) {
+ // if the new animation is class-based then we can just tack that on
+ return !newAnimation.structural && hasAnimationClasses(newAnimation);
+ });
- var groupBases = [
- 0, 0,
- 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
- 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
- 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
- 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
- 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
- ];
+ rules.skip.push(function(newAnimation, currentAnimation) {
+ // there is no need to animate anything if no classes are being added and
+ // there is no structural animation that will be triggered
+ return !newAnimation.structural && !hasAnimationClasses(newAnimation);
+ });
- BN.prototype.toString = function toString (base, padding) {
- base = base || 10;
- padding = padding | 0 || 1;
+ rules.skip.push(function(newAnimation, currentAnimation) {
+ // why should we trigger a new structural animation if the element will
+ // be removed from the DOM anyway?
+ return currentAnimation.event === 'leave' && newAnimation.structural;
+ });
- var out;
- if (base === 16 || base === 'hex') {
- out = '';
- var off = 0;
- var carry = 0;
- for (var i = 0; i < this.length; i++) {
- var w = this.words[i];
- var word = (((w << off) | carry) & 0xffffff).toString(16);
- carry = (w >>> (24 - off)) & 0xffffff;
- if (carry !== 0 || i !== this.length - 1) {
- out = zeros[6 - word.length] + word + out;
- } else {
- out = word + out;
- }
- off += 2;
- if (off >= 26) {
- off -= 26;
- i--;
- }
- }
- if (carry !== 0) {
- out = carry.toString(16) + out;
- }
- while (out.length % padding !== 0) {
- out = '0' + out;
- }
- if (this.negative !== 0) {
- out = '-' + out;
- }
- return out;
- }
+ rules.skip.push(function(newAnimation, currentAnimation) {
+ // if there is an ongoing current animation then don't even bother running the class-based animation
+ return currentAnimation.structural && currentAnimation.state === RUNNING_STATE && !newAnimation.structural;
+ });
- if (base === (base | 0) && base >= 2 && base <= 36) {
- // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
- var groupSize = groupSizes[base];
- // var groupBase = Math.pow(base, groupSize);
- var groupBase = groupBases[base];
- out = '';
- var c = this.clone();
- c.negative = 0;
- while (!c.isZero()) {
- var r = c.modn(groupBase).toString(base);
- c = c.idivn(groupBase);
+ rules.cancel.push(function(newAnimation, currentAnimation) {
+ // there can never be two structural animations running at the same time
+ return currentAnimation.structural && newAnimation.structural;
+ });
- if (!c.isZero()) {
- out = zeros[groupSize - r.length] + r + out;
- } else {
- out = r + out;
- }
- }
- if (this.isZero()) {
- out = '0' + out;
- }
- while (out.length % padding !== 0) {
- out = '0' + out;
- }
- if (this.negative !== 0) {
- out = '-' + out;
- }
- return out;
- }
+ rules.cancel.push(function(newAnimation, currentAnimation) {
+ // if the previous animation is already running, but the new animation will
+ // be triggered, but the new animation is structural
+ return currentAnimation.state === RUNNING_STATE && newAnimation.structural;
+ });
- assert(false, 'Base should be between 2 and 36');
- };
+ rules.cancel.push(function(newAnimation, currentAnimation) {
+ // cancel the animation if classes added / removed in both animation cancel each other out,
+ // but only if the current animation isn't structural
- BN.prototype.toNumber = function toNumber () {
- var ret = this.words[0];
- if (this.length === 2) {
- ret += this.words[1] * 0x4000000;
- } else if (this.length === 3 && this.words[2] === 0x01) {
- // NOTE: at this stage it is known that the top bit is set
- ret += 0x10000000000000 + (this.words[1] * 0x4000000);
- } else if (this.length > 2) {
- assert(false, 'Number can only safely store up to 53 bits');
- }
- return (this.negative !== 0) ? -ret : ret;
- };
+ if (currentAnimation.structural) return false;
- BN.prototype.toJSON = function toJSON () {
- return this.toString(16);
- };
+ var nA = newAnimation.addClass;
+ var nR = newAnimation.removeClass;
+ var cA = currentAnimation.addClass;
+ var cR = currentAnimation.removeClass;
- BN.prototype.toBuffer = function toBuffer (endian, length) {
- assert(typeof Buffer !== 'undefined');
- return this.toArrayLike(Buffer, endian, length);
- };
+ // early detection to save the global CPU shortage :)
+ if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) {
+ return false;
+ }
- BN.prototype.toArray = function toArray (endian, length) {
- return this.toArrayLike(Array, endian, length);
- };
+ return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
+ });
- BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
- var byteLength = this.byteLength();
- var reqLength = length || Math.max(1, byteLength);
- assert(byteLength <= reqLength, 'byte array longer than desired length');
- assert(reqLength > 0, 'Requested array length <= 0');
+ this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$Map',
+ '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', '$$forceReflow',
+ '$$isDocumentHidden',
+ function($$rAF, $rootScope, $rootElement, $document, $$Map,
+ $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow,
+ $$isDocumentHidden) {
- this.strip();
- var littleEndian = endian === 'le';
- var res = new ArrayType(reqLength);
+ var activeAnimationsLookup = new $$Map();
+ var disabledElementsLookup = new $$Map();
+ var animationsEnabled = null;
- var b, i;
- var q = this.clone();
- if (!littleEndian) {
- // Assume big-endian
- for (i = 0; i < reqLength - byteLength; i++) {
- res[i] = 0;
- }
+ function removeFromDisabledElementsLookup(evt) {
+ disabledElementsLookup.delete(evt.target);
+ }
- for (i = 0; !q.isZero(); i++) {
- b = q.andln(0xff);
- q.iushrn(8);
+ function postDigestTaskFactory() {
+ var postDigestCalled = false;
+ return function(fn) {
+ // we only issue a call to postDigest before
+ // it has first passed. This prevents any callbacks
+ // from not firing once the animation has completed
+ // since it will be out of the digest cycle.
+ if (postDigestCalled) {
+ fn();
+ } else {
+ $rootScope.$$postDigest(function() {
+ postDigestCalled = true;
+ fn();
+ });
+ }
+ };
+ }
- res[reqLength - i - 1] = b;
- }
- } else {
- for (i = 0; !q.isZero(); i++) {
- b = q.andln(0xff);
- q.iushrn(8);
+ // Wait until all directive and route-related templates are downloaded and
+ // compiled. The $templateRequest.totalPendingRequests variable keeps track of
+ // all of the remote templates being currently downloaded. If there are no
+ // templates currently downloading then the watcher will still fire anyway.
+ var deregisterWatch = $rootScope.$watch(
+ function() { return $templateRequest.totalPendingRequests === 0; },
+ function(isEmpty) {
+ if (!isEmpty) return;
+ deregisterWatch();
- res[i] = b;
+ // Now that all templates have been downloaded, $animate will wait until
+ // the post digest queue is empty before enabling animations. By having two
+ // calls to $postDigest calls we can ensure that the flag is enabled at the
+ // very end of the post digest queue. Since all of the animations in $animate
+ // use $postDigest, it's important that the code below executes at the end.
+ // This basically means that the page is fully downloaded and compiled before
+ // any animations are triggered.
+ $rootScope.$$postDigest(function() {
+ $rootScope.$$postDigest(function() {
+ // we check for null directly in the event that the application already called
+ // .enabled() with whatever arguments that it provided it with
+ if (animationsEnabled === null) {
+ animationsEnabled = true;
+ }
+ });
+ });
}
+ );
- for (; i < reqLength; i++) {
- res[i] = 0;
- }
- }
+ var callbackRegistry = Object.create(null);
- return res;
- };
+ // remember that the `customFilter`/`classNameFilter` are set during the
+ // provider/config stage therefore we can optimize here and setup helper functions
+ var customFilter = $animateProvider.customFilter();
+ var classNameFilter = $animateProvider.classNameFilter();
+ var returnTrue = function() { return true; };
- if (Math.clz32) {
- BN.prototype._countBits = function _countBits (w) {
- return 32 - Math.clz32(w);
- };
- } else {
- BN.prototype._countBits = function _countBits (w) {
- var t = w;
- var r = 0;
- if (t >= 0x1000) {
- r += 13;
- t >>>= 13;
- }
- if (t >= 0x40) {
- r += 7;
- t >>>= 7;
- }
- if (t >= 0x8) {
- r += 4;
- t >>>= 4;
- }
- if (t >= 0x02) {
- r += 2;
- t >>>= 2;
- }
- return r + t;
+ var isAnimatableByFilter = customFilter || returnTrue;
+ var isAnimatableClassName = !classNameFilter ? returnTrue : function(node, options) {
+ var className = [node.getAttribute('class'), options.addClass, options.removeClass].join(' ');
+ return classNameFilter.test(className);
};
- }
- BN.prototype._zeroBits = function _zeroBits (w) {
- // Short-cut
- if (w === 0) return 26;
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
- var t = w;
- var r = 0;
- if ((t & 0x1fff) === 0) {
- r += 13;
- t >>>= 13;
- }
- if ((t & 0x7f) === 0) {
- r += 7;
- t >>>= 7;
- }
- if ((t & 0xf) === 0) {
- r += 4;
- t >>>= 4;
- }
- if ((t & 0x3) === 0) {
- r += 2;
- t >>>= 2;
- }
- if ((t & 0x1) === 0) {
- r++;
+ function normalizeAnimationDetails(element, animation) {
+ return mergeAnimationDetails(element, animation, {});
}
- return r;
- };
-
- // Return number of used bits in a BN
- BN.prototype.bitLength = function bitLength () {
- var w = this.words[this.length - 1];
- var hi = this._countBits(w);
- return (this.length - 1) * 26 + hi;
- };
- function toBitArray (num) {
- var w = new Array(num.bitLength());
+ // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
+ var contains = window.Node.prototype.contains || /** @this */ function(arg) {
+ // eslint-disable-next-line no-bitwise
+ return this === arg || !!(this.compareDocumentPosition(arg) & 16);
+ };
- for (var bit = 0; bit < w.length; bit++) {
- var off = (bit / 26) | 0;
- var wbit = bit % 26;
+ function findCallbacks(targetParentNode, targetNode, event) {
+ var matches = [];
+ var entries = callbackRegistry[event];
+ if (entries) {
+ forEach(entries, function(entry) {
+ if (contains.call(entry.node, targetNode)) {
+ matches.push(entry.callback);
+ } else if (event === 'leave' && contains.call(entry.node, targetParentNode)) {
+ matches.push(entry.callback);
+ }
+ });
+ }
- w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
+ return matches;
}
- return w;
- }
-
- // Number of trailing zero bits
- BN.prototype.zeroBits = function zeroBits () {
- if (this.isZero()) return 0;
-
- var r = 0;
- for (var i = 0; i < this.length; i++) {
- var b = this._zeroBits(this.words[i]);
- r += b;
- if (b !== 26) break;
+ function filterFromRegistry(list, matchContainer, matchCallback) {
+ var containerNode = extractElementNode(matchContainer);
+ return list.filter(function(entry) {
+ var isMatch = entry.node === containerNode &&
+ (!matchCallback || entry.callback === matchCallback);
+ return !isMatch;
+ });
}
- return r;
- };
-
- BN.prototype.byteLength = function byteLength () {
- return Math.ceil(this.bitLength() / 8);
- };
- BN.prototype.toTwos = function toTwos (width) {
- if (this.negative !== 0) {
- return this.abs().inotn(width).iaddn(1);
+ function cleanupEventListeners(phase, node) {
+ if (phase === 'close' && !node.parentNode) {
+ // If the element is not attached to a parentNode, it has been removed by
+ // the domOperation, and we can safely remove the event callbacks
+ $animate.off(node);
+ }
}
- return this.clone();
- };
- BN.prototype.fromTwos = function fromTwos (width) {
- if (this.testn(width - 1)) {
- return this.notn(width).iaddn(1).ineg();
- }
- return this.clone();
- };
+ var $animate = {
+ on: function(event, container, callback) {
+ var node = extractElementNode(container);
+ callbackRegistry[event] = callbackRegistry[event] || [];
+ callbackRegistry[event].push({
+ node: node,
+ callback: callback
+ });
- BN.prototype.isNeg = function isNeg () {
- return this.negative !== 0;
- };
+ // Remove the callback when the element is removed from the DOM
+ jqLite(container).on('$destroy', function() {
+ var animationDetails = activeAnimationsLookup.get(node);
- // Return negative clone of `this`
- BN.prototype.neg = function neg () {
- return this.clone().ineg();
- };
+ if (!animationDetails) {
+ // If there's an animation ongoing, the callback calling code will remove
+ // the event listeners. If we'd remove here, the callbacks would be removed
+ // before the animation ends
+ $animate.off(event, container, callback);
+ }
+ });
+ },
- BN.prototype.ineg = function ineg () {
- if (!this.isZero()) {
- this.negative ^= 1;
- }
+ off: function(event, container, callback) {
+ if (arguments.length === 1 && !isString(arguments[0])) {
+ container = arguments[0];
+ for (var eventType in callbackRegistry) {
+ callbackRegistry[eventType] = filterFromRegistry(callbackRegistry[eventType], container);
+ }
- return this;
- };
+ return;
+ }
- // Or `num` with `this` in-place
- BN.prototype.iuor = function iuor (num) {
- while (this.length < num.length) {
- this.words[this.length++] = 0;
- }
+ var entries = callbackRegistry[event];
+ if (!entries) return;
- for (var i = 0; i < num.length; i++) {
- this.words[i] = this.words[i] | num.words[i];
- }
+ callbackRegistry[event] = arguments.length === 1
+ ? null
+ : filterFromRegistry(entries, container, callback);
+ },
- return this.strip();
- };
+ pin: function(element, parentElement) {
+ assertArg(isElement(element), 'element', 'not an element');
+ assertArg(isElement(parentElement), 'parentElement', 'not an element');
+ element.data(NG_ANIMATE_PIN_DATA, parentElement);
+ },
- BN.prototype.ior = function ior (num) {
- assert((this.negative | num.negative) === 0);
- return this.iuor(num);
- };
+ push: function(element, event, options, domOperation) {
+ options = options || {};
+ options.domOperation = domOperation;
+ return queueAnimation(element, event, options);
+ },
- // Or `num` with `this`
- BN.prototype.or = function or (num) {
- if (this.length > num.length) return this.clone().ior(num);
- return num.clone().ior(this);
- };
+ // this method has four signatures:
+ // () - global getter
+ // (bool) - global setter
+ // (element) - element getter
+ // (element, bool) - element setter
+ enabled: function(element, bool) {
+ var argCount = arguments.length;
- BN.prototype.uor = function uor (num) {
- if (this.length > num.length) return this.clone().iuor(num);
- return num.clone().iuor(this);
- };
+ if (argCount === 0) {
+ // () - Global getter
+ bool = !!animationsEnabled;
+ } else {
+ var hasElement = isElement(element);
- // And `num` with `this` in-place
- BN.prototype.iuand = function iuand (num) {
- // b = min-length(num, this)
- var b;
- if (this.length > num.length) {
- b = num;
- } else {
- b = this;
- }
+ if (!hasElement) {
+ // (bool) - Global setter
+ bool = animationsEnabled = !!element;
+ } else {
+ var node = getDomNode(element);
- for (var i = 0; i < b.length; i++) {
- this.words[i] = this.words[i] & num.words[i];
- }
+ if (argCount === 1) {
+ // (element) - Element getter
+ 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);
+ }
+ }
+ }
- this.length = b.length;
+ return bool;
+ }
+ };
- return this.strip();
- };
+ return $animate;
- BN.prototype.iand = function iand (num) {
- assert((this.negative | num.negative) === 0);
- return this.iuand(num);
- };
+ function queueAnimation(originalElement, event, initialOptions) {
+ // we always make a copy of the options since
+ // there should never be any side effects on
+ // the input data when running `$animateCss`.
+ var options = copy(initialOptions);
- // And `num` with `this`
- BN.prototype.and = function and (num) {
- if (this.length > num.length) return this.clone().iand(num);
- return num.clone().iand(this);
- };
+ var element = stripCommentsFromElement(originalElement);
+ var node = getDomNode(element);
+ var parentNode = node && node.parentNode;
- BN.prototype.uand = function uand (num) {
- if (this.length > num.length) return this.clone().iuand(num);
- return num.clone().iuand(this);
- };
+ options = prepareAnimationOptions(options);
- // Xor `num` with `this` in-place
- BN.prototype.iuxor = function iuxor (num) {
- // a.length > b.length
- var a;
- var b;
- if (this.length > num.length) {
- a = this;
- b = num;
- } else {
- a = num;
- b = this;
- }
+ // we create a fake runner with a working promise.
+ // These methods will become available after the digest has passed
+ var runner = new $$AnimateRunner();
- for (var i = 0; i < b.length; i++) {
- this.words[i] = a.words[i] ^ b.words[i];
- }
+ // this is used to trigger callbacks in postDigest mode
+ var runInNextPostDigestOrNow = postDigestTaskFactory();
- if (this !== a) {
- for (; i < a.length; i++) {
- this.words[i] = a.words[i];
+ if (isArray(options.addClass)) {
+ options.addClass = options.addClass.join(' ');
}
- }
- this.length = a.length;
+ if (options.addClass && !isString(options.addClass)) {
+ options.addClass = null;
+ }
- return this.strip();
- };
+ if (isArray(options.removeClass)) {
+ options.removeClass = options.removeClass.join(' ');
+ }
- BN.prototype.ixor = function ixor (num) {
- assert((this.negative | num.negative) === 0);
- return this.iuxor(num);
- };
+ if (options.removeClass && !isString(options.removeClass)) {
+ options.removeClass = null;
+ }
- // Xor `num` with `this`
- BN.prototype.xor = function xor (num) {
- if (this.length > num.length) return this.clone().ixor(num);
- return num.clone().ixor(this);
- };
+ if (options.from && !isObject(options.from)) {
+ options.from = null;
+ }
- BN.prototype.uxor = function uxor (num) {
- if (this.length > num.length) return this.clone().iuxor(num);
- return num.clone().iuxor(this);
- };
+ if (options.to && !isObject(options.to)) {
+ options.to = null;
+ }
- // Not ``this`` with ``width`` bitwidth
- BN.prototype.inotn = function inotn (width) {
- assert(typeof width === 'number' && width >= 0);
+ // If animations are hard-disabled for the whole application there is no need to continue.
+ // There are also situations where a directive issues an animation for a jqLite wrapper that
+ // contains only comment nodes. In this case, there is no way we can perform an animation.
+ if (!animationsEnabled ||
+ !node ||
+ !isAnimatableByFilter(node, event, initialOptions) ||
+ !isAnimatableClassName(node, options)) {
+ close();
+ return runner;
+ }
- var bytesNeeded = Math.ceil(width / 26) | 0;
- var bitsLeft = width % 26;
+ var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
- // Extend the buffer with leading zeroes
- this._expand(bytesNeeded);
+ var documentHidden = $$isDocumentHidden();
- if (bitsLeft > 0) {
- bytesNeeded--;
- }
+ // This is a hard disable of all animations the element itself, therefore there is no need to
+ // continue further past this point if not enabled
+ // Animations are also disabled if the document is currently hidden (page is not visible
+ // to the user), because browsers slow down or do not flush calls to requestAnimationFrame
+ var skipAnimations = documentHidden || disabledElementsLookup.get(node);
+ var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
+ var hasExistingAnimation = !!existingAnimation.state;
- // Handle complete words
- for (var i = 0; i < bytesNeeded; i++) {
- this.words[i] = ~this.words[i] & 0x3ffffff;
- }
+ // there is no point in traversing the same collection of parent ancestors if a followup
+ // animation will be run on the same element that already did all that checking work
+ if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state !== PRE_DIGEST_STATE)) {
+ skipAnimations = !areAnimationsAllowed(node, parentNode, event);
+ }
- // Handle the residue
- if (bitsLeft > 0) {
- this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
- }
+ if (skipAnimations) {
+ // Callbacks should fire even if the document is hidden (regression fix for issue #14120)
+ if (documentHidden) notifyProgress(runner, event, 'start', getEventData(options));
+ close();
+ if (documentHidden) notifyProgress(runner, event, 'close', getEventData(options));
+ return runner;
+ }
- // And remove leading zeroes
- return this.strip();
- };
+ if (isStructural) {
+ closeChildAnimations(node);
+ }
- BN.prototype.notn = function notn (width) {
- return this.clone().inotn(width);
- };
+ var newAnimation = {
+ structural: isStructural,
+ element: element,
+ event: event,
+ addClass: options.addClass,
+ removeClass: options.removeClass,
+ close: close,
+ options: options,
+ runner: runner
+ };
- // Set `bit` of `this`
- BN.prototype.setn = function setn (bit, val) {
- assert(typeof bit === 'number' && bit >= 0);
+ if (hasExistingAnimation) {
+ var skipAnimationFlag = isAllowed('skip', newAnimation, existingAnimation);
+ if (skipAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ close();
+ return runner;
+ } else {
+ mergeAnimationDetails(element, existingAnimation, newAnimation);
+ return existingAnimation.runner;
+ }
+ }
+ var cancelAnimationFlag = isAllowed('cancel', newAnimation, existingAnimation);
+ if (cancelAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ // this will end the animation right away and it is safe
+ // to do so since the animation is already running and the
+ // runner callback code will run in async
+ existingAnimation.runner.end();
+ } else if (existingAnimation.structural) {
+ // this means that the animation is queued into a digest, but
+ // hasn't started yet. Therefore it is safe to run the close
+ // method which will call the runner methods in async.
+ existingAnimation.close();
+ } else {
+ // this will merge the new animation options into existing animation options
+ mergeAnimationDetails(element, existingAnimation, newAnimation);
- var off = (bit / 26) | 0;
- var wbit = bit % 26;
+ return existingAnimation.runner;
+ }
+ } else {
+ // a joined animation means that this animation will take over the existing one
+ // so an example would involve a leave animation taking over an enter. Then when
+ // the postDigest kicks in the enter will be ignored.
+ var joinAnimationFlag = isAllowed('join', newAnimation, existingAnimation);
+ if (joinAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ normalizeAnimationDetails(element, newAnimation);
+ } else {
+ applyGeneratedPreparationClasses($$jqLite, element, isStructural ? event : null, options);
- this._expand(off + 1);
+ event = newAnimation.event = existingAnimation.event;
+ options = mergeAnimationDetails(element, existingAnimation, newAnimation);
- if (val) {
- this.words[off] = this.words[off] | (1 << wbit);
- } else {
- this.words[off] = this.words[off] & ~(1 << wbit);
- }
+ //we return the same runner since only the option values of this animation will
+ //be fed into the `existingAnimation`.
+ return existingAnimation.runner;
+ }
+ }
+ }
+ } else {
+ // normalization in this case means that it removes redundant CSS classes that
+ // already exist (addClass) or do not exist (removeClass) on the element
+ normalizeAnimationDetails(element, newAnimation);
+ }
- return this.strip();
- };
+ // when the options are merged and cleaned up we may end up not having to do
+ // an animation at all, therefore we should check this before issuing a post
+ // digest callback. Structural animations will always run no matter what.
+ var isValidAnimation = newAnimation.structural;
+ if (!isValidAnimation) {
+ // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
+ isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
+ || hasAnimationClasses(newAnimation);
+ }
- // Add `num` to `this` in-place
- BN.prototype.iadd = function iadd (num) {
- var r;
+ if (!isValidAnimation) {
+ close();
+ clearElementAnimationState(node);
+ return runner;
+ }
- // negative + positive
- if (this.negative !== 0 && num.negative === 0) {
- this.negative = 0;
- r = this.isub(num);
- this.negative ^= 1;
- return this._normSign();
+ // the counter keeps track of cancelled animations
+ var counter = (existingAnimation.counter || 0) + 1;
+ newAnimation.counter = counter;
- // positive + negative
- } else if (this.negative === 0 && num.negative !== 0) {
- num.negative = 0;
- r = this.isub(num);
- num.negative = 1;
- return r._normSign();
- }
+ markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation);
- // a.length > b.length
- var a, b;
- if (this.length > num.length) {
- a = this;
- b = num;
- } else {
- a = num;
- b = this;
+ $rootScope.$$postDigest(function() {
+ // It is possible that the DOM nodes inside `originalElement` have been replaced. This can
+ // happen if the animated element is a transcluded clone and also has a `templateUrl`
+ // directive on it. Therefore, we must recreate `element` in order to interact with the
+ // actual DOM nodes.
+ // Note: We still need to use the old `node` for certain things, such as looking up in
+ // HashMaps where it was used as the key.
+
+ element = stripCommentsFromElement(originalElement);
+
+ var animationDetails = activeAnimationsLookup.get(node);
+ var animationCancelled = !animationDetails;
+ animationDetails = animationDetails || {};
+
+ // if addClass/removeClass is called before something like enter then the
+ // registered parent element may not be present. The code below will ensure
+ // that a final value for parent element is obtained
+ var parentElement = element.parent() || [];
+
+ // animate/structural/class-based animations all have requirements. Otherwise there
+ // is no point in performing an animation. The parent node must also be set.
+ var isValidAnimation = parentElement.length > 0
+ && (animationDetails.event === 'animate'
+ || animationDetails.structural
+ || hasAnimationClasses(animationDetails));
+
+ // this means that the previous animation was cancelled
+ // even if the follow-up animation is the same event
+ if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) {
+ // if another animation did not take over then we need
+ // to make sure that the domOperation and options are
+ // handled accordingly
+ if (animationCancelled) {
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ }
+
+ // if the event changed from something like enter to leave then we do
+ // it, otherwise if it's the same then the end result will be the same too
+ if (animationCancelled || (isStructural && animationDetails.event !== event)) {
+ options.domOperation();
+ runner.end();
+ }
+
+ // in the event that the element animation was not cancelled or a follow-up animation
+ // isn't allowed to animate from here then we need to clear the state of the element
+ // so that any future animations won't read the expired animation data.
+ if (!isValidAnimation) {
+ clearElementAnimationState(node);
+ }
+
+ return;
+ }
+
+ // this combined multiple class to addClass / removeClass into a setClass event
+ // so long as a structural event did not take over the animation
+ event = !animationDetails.structural && hasAnimationClasses(animationDetails, true)
+ ? 'setClass'
+ : animationDetails.event;
+
+ markElementAnimationState(node, RUNNING_STATE);
+ var realRunner = $$animation(element, event, animationDetails.options);
+
+ // this will update the runner's flow-control events based on
+ // the `realRunner` object.
+ runner.setHost(realRunner);
+ notifyProgress(runner, event, 'start', getEventData(options));
+
+ realRunner.done(function(status) {
+ close(!status);
+ var animationDetails = activeAnimationsLookup.get(node);
+ if (animationDetails && animationDetails.counter === counter) {
+ clearElementAnimationState(node);
+ }
+ notifyProgress(runner, event, 'close', getEventData(options));
+ });
+ });
+
+ return runner;
+
+ function notifyProgress(runner, event, phase, data) {
+ runInNextPostDigestOrNow(function() {
+ var callbacks = findCallbacks(parentNode, node, event);
+ if (callbacks.length) {
+ // do not optimize this call here to RAF because
+ // we don't know how heavy the callback code here will
+ // be and if this code is buffered then this can
+ // lead to a performance regression.
+ $$rAF(function() {
+ forEach(callbacks, function(callback) {
+ callback(element, phase, data);
+ });
+ cleanupEventListeners(phase, node);
+ });
+ } else {
+ cleanupEventListeners(phase, node);
+ }
+ });
+ runner.progress(event, phase, data);
+ }
+
+ function close(reject) {
+ clearGeneratedClasses(element, options);
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ options.domOperation();
+ runner.complete(!reject);
+ }
}
- var carry = 0;
- for (var i = 0; i < b.length; i++) {
- r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
- this.words[i] = r & 0x3ffffff;
- carry = r >>> 26;
+ function closeChildAnimations(node) {
+ var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']');
+ forEach(children, function(child) {
+ var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME), 10);
+ var animationDetails = activeAnimationsLookup.get(child);
+ if (animationDetails) {
+ switch (state) {
+ case RUNNING_STATE:
+ animationDetails.runner.end();
+ /* falls through */
+ case PRE_DIGEST_STATE:
+ activeAnimationsLookup.delete(child);
+ break;
+ }
+ }
+ });
}
- for (; carry !== 0 && i < a.length; i++) {
- r = (a.words[i] | 0) + carry;
- this.words[i] = r & 0x3ffffff;
- carry = r >>> 26;
+
+ function clearElementAnimationState(node) {
+ node.removeAttribute(NG_ANIMATE_ATTR_NAME);
+ activeAnimationsLookup.delete(node);
}
- this.length = a.length;
- if (carry !== 0) {
- this.words[this.length] = carry;
- this.length++;
- // Copy the rest of the words
- } else if (a !== this) {
- for (; i < a.length; i++) {
- this.words[i] = a.words[i];
+ /**
+ * This fn returns false if any of the following is true:
+ * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
+ * b) a parent element has an ongoing structural animation, and animateChildren is false
+ * c) the element is not a child of the body
+ * d) the element is not a child of the $rootElement
+ */
+ function areAnimationsAllowed(node, parentNode, event) {
+ var bodyNode = $document[0].body;
+ var rootNode = getDomNode($rootElement);
+
+ var bodyNodeDetected = (node === bodyNode) || node.nodeName === 'HTML';
+ var rootNodeDetected = (node === rootNode);
+ var parentAnimationDetected = false;
+ var elementDisabled = disabledElementsLookup.get(node);
+ var animateChildren;
+
+ var parentHost = jqLite.data(node, NG_ANIMATE_PIN_DATA);
+ if (parentHost) {
+ parentNode = getDomNode(parentHost);
}
- }
- return this;
- };
+ while (parentNode) {
+ if (!rootNodeDetected) {
+ // 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);
+ }
- // Add `num` to `this`
- BN.prototype.add = function add (num) {
- var res;
- if (num.negative !== 0 && this.negative === 0) {
- num.negative = 0;
- res = this.sub(num);
- num.negative ^= 1;
- return res;
- } else if (num.negative === 0 && this.negative !== 0) {
- this.negative = 0;
- res = num.sub(this);
- this.negative = 1;
- return res;
- }
+ if (parentNode.nodeType !== ELEMENT_NODE) {
+ // no point in inspecting the #document element
+ break;
+ }
- if (this.length > num.length) return this.clone().iadd(num);
+ var details = activeAnimationsLookup.get(parentNode) || {};
+ // either an enter, leave or move animation will commence
+ // therefore we can't allow any animations to take place
+ // but if a parent animation is class-based then that's ok
+ if (!parentAnimationDetected) {
+ var parentNodeDisabled = disabledElementsLookup.get(parentNode);
- return num.clone().iadd(this);
- };
+ if (parentNodeDisabled === true && elementDisabled !== false) {
+ // disable animations if the user hasn't explicitly enabled animations on the
+ // current element
+ elementDisabled = true;
+ // element is disabled via parent element, no need to check anything else
+ break;
+ } else if (parentNodeDisabled === false) {
+ elementDisabled = false;
+ }
+ parentAnimationDetected = details.structural;
+ }
- // Subtract `num` from `this` in-place
- BN.prototype.isub = function isub (num) {
- // this - (-num) = this + num
- if (num.negative !== 0) {
- num.negative = 0;
- var r = this.iadd(num);
- num.negative = 1;
- return r._normSign();
+ if (isUndefined(animateChildren) || animateChildren === true) {
+ var value = jqLite.data(parentNode, NG_ANIMATE_CHILDREN_DATA);
+ if (isDefined(value)) {
+ animateChildren = value;
+ }
+ }
- // -this - num = -(this + num)
- } else if (this.negative !== 0) {
- this.negative = 0;
- this.iadd(num);
- this.negative = 1;
- return this._normSign();
- }
+ // there is no need to continue traversing at this point
+ if (parentAnimationDetected && animateChildren === false) break;
- // At this point both numbers are positive
- var cmp = this.cmp(num);
+ if (!bodyNodeDetected) {
+ // we also need to ensure that the element is or will be a part of the body element
+ // otherwise it is pointless to even issue an animation to be rendered
+ bodyNodeDetected = (parentNode === bodyNode);
+ }
- // Optimization - zeroify
- if (cmp === 0) {
- this.negative = 0;
- this.length = 1;
- this.words[0] = 0;
- return this;
- }
+ if (bodyNodeDetected && rootNodeDetected) {
+ // If both body and root have been found, any other checks are pointless,
+ // as no animation data should live outside the application
+ break;
+ }
- // a > b
- var a, b;
- if (cmp > 0) {
- a = this;
- b = num;
- } else {
- a = num;
- b = this;
- }
+ if (!rootNodeDetected) {
+ // If `rootNode` is not detected, check if `parentNode` is pinned to another element
+ parentHost = jqLite.data(parentNode, NG_ANIMATE_PIN_DATA);
+ if (parentHost) {
+ // The pin target element becomes the next parent element
+ parentNode = getDomNode(parentHost);
+ continue;
+ }
+ }
- var carry = 0;
- for (var i = 0; i < b.length; i++) {
- r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
- carry = r >> 26;
- this.words[i] = r & 0x3ffffff;
+ parentNode = parentNode.parentNode;
+ }
+
+ var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true;
+ return allowAnimation && rootNodeDetected && bodyNodeDetected;
}
- for (; carry !== 0 && i < a.length; i++) {
- r = (a.words[i] | 0) + carry;
- carry = r >> 26;
- this.words[i] = r & 0x3ffffff;
+
+ function markElementAnimationState(node, state, details) {
+ details = details || {};
+ details.state = state;
+
+ node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
+
+ var oldValue = activeAnimationsLookup.get(node);
+ var newValue = oldValue
+ ? extend(oldValue, details)
+ : details;
+ activeAnimationsLookup.set(node, newValue);
}
+ }];
+}];
- // Copy rest of the words
- if (carry === 0 && i < a.length && a !== this) {
- for (; i < a.length; i++) {
- this.words[i] = a.words[i];
+/** @this */
+var $$AnimateCacheProvider = function() {
+
+ var KEY = '$$ngAnimateParentKey';
+ var parentCounter = 0;
+ var cache = Object.create(null);
+
+ this.$get = [function() {
+ return {
+ cacheKey: function(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(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() {
+ cache = Object.create(null);
+ },
+
+ count: function(key) {
+ var entry = cache[key];
+ return entry ? entry.total : 0;
+ },
+
+ get: function(key) {
+ var entry = cache[key];
+ return entry && entry.value;
+ },
+
+ put: function(key, value, isValid) {
+ if (!cache[key]) {
+ cache[key] = { total: 1, value: value, isValid: isValid };
+ } else {
+ cache[key].total++;
+ cache[key].value = value;
+ }
}
- }
+ };
+ }];
+};
- this.length = Math.max(this.length, i);
+/* exported $$AnimationProvider */
- if (a !== this) {
- this.negative = 1;
- }
+var $$AnimationProvider = ['$animateProvider', /** @this */ function($animateProvider) {
+ var NG_ANIMATE_REF_ATTR = 'ng-animate-ref';
- return this.strip();
- };
+ var drivers = this.drivers = [];
- // Subtract `num` from `this`
- BN.prototype.sub = function sub (num) {
- return this.clone().isub(num);
- };
+ var RUNNER_STORAGE_KEY = '$$animationRunner';
+ var PREPARE_CLASSES_KEY = '$$animatePrepareClasses';
- function smallMulTo (self, num, out) {
- out.negative = num.negative ^ self.negative;
- var len = (self.length + num.length) | 0;
- out.length = len;
- len = (len - 1) | 0;
+ function setRunner(element, runner) {
+ element.data(RUNNER_STORAGE_KEY, runner);
+ }
- // Peel one iteration (compiler can't do it, because of code complexity)
- var a = self.words[0] | 0;
- var b = num.words[0] | 0;
- var r = a * b;
+ function removeRunner(element) {
+ element.removeData(RUNNER_STORAGE_KEY);
+ }
- var lo = r & 0x3ffffff;
- var carry = (r / 0x4000000) | 0;
- out.words[0] = lo;
+ function getRunner(element) {
+ return element.data(RUNNER_STORAGE_KEY);
+ }
- for (var k = 1; k < len; k++) {
- // Sum all words with the same `i + j = k` and accumulate `ncarry`,
- // note that ncarry could be >= 0x3ffffff
- var ncarry = carry >>> 26;
- var rword = carry & 0x3ffffff;
- var maxJ = Math.min(k, num.length - 1);
- for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
- var i = (k - j) | 0;
- a = self.words[i] | 0;
- b = num.words[j] | 0;
- r = a * b + rword;
- ncarry += (r / 0x4000000) | 0;
- rword = r & 0x3ffffff;
+ this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler', '$$animateCache',
+ function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler, $$animateCache) {
+
+ var animationQueue = [];
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+
+ function sortAnimations(animations) {
+ var tree = { children: [] };
+ var i, lookup = new $$Map();
+
+ // this is done first beforehand so that the map
+ // is filled with a list of the elements that will be animated
+ for (i = 0; i < animations.length; i++) {
+ var animation = animations[i];
+ lookup.set(animation.domNode, animations[i] = {
+ domNode: animation.domNode,
+ element: animation.element,
+ fn: animation.fn,
+ children: []
+ });
+ }
+
+ for (i = 0; i < animations.length; i++) {
+ processNode(animations[i]);
+ }
+
+ return flatten(tree);
+
+ function processNode(entry) {
+ if (entry.processed) return entry;
+ entry.processed = true;
+
+ var elementNode = entry.domNode;
+ var parentNode = elementNode.parentNode;
+ lookup.set(elementNode, entry);
+
+ var parentEntry;
+ while (parentNode) {
+ parentEntry = lookup.get(parentNode);
+ if (parentEntry) {
+ if (!parentEntry.processed) {
+ parentEntry = processNode(parentEntry);
+ }
+ break;
+ }
+ parentNode = parentNode.parentNode;
+ }
+
+ (parentEntry || tree).children.push(entry);
+ return entry;
+ }
+
+ function flatten(tree) {
+ var result = [];
+ var queue = [];
+ var i;
+
+ for (i = 0; i < tree.children.length; i++) {
+ queue.push(tree.children[i]);
+ }
+
+ var remainingLevelEntries = queue.length;
+ var nextLevelEntries = 0;
+ var row = [];
+
+ for (i = 0; i < queue.length; i++) {
+ var entry = queue[i];
+ if (remainingLevelEntries <= 0) {
+ remainingLevelEntries = nextLevelEntries;
+ nextLevelEntries = 0;
+ result.push(row);
+ row = [];
+ }
+ row.push(entry);
+ entry.children.forEach(function(childEntry) {
+ nextLevelEntries++;
+ queue.push(childEntry);
+ });
+ remainingLevelEntries--;
+ }
+
+ if (row.length) {
+ result.push(row);
+ }
+
+ return result;
}
- out.words[k] = rword | 0;
- carry = ncarry | 0;
- }
- if (carry !== 0) {
- out.words[k] = carry | 0;
- } else {
- out.length--;
}
- return out.strip();
- }
+ // TODO(matsko): document the signature in a better way
+ return function(element, event, options) {
+ options = prepareAnimationOptions(options);
+ var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
- // TODO(indutny): it may be reasonable to omit it for users who don't need
- // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
- // multiplication (like elliptic secp256k1).
- var comb10MulTo = function comb10MulTo (self, num, out) {
- var a = self.words;
- var b = num.words;
- var o = out.words;
- var c = 0;
- var lo;
- var mid;
- var hi;
- var a0 = a[0] | 0;
- var al0 = a0 & 0x1fff;
- var ah0 = a0 >>> 13;
- var a1 = a[1] | 0;
- var al1 = a1 & 0x1fff;
- var ah1 = a1 >>> 13;
- var a2 = a[2] | 0;
- var al2 = a2 & 0x1fff;
- var ah2 = a2 >>> 13;
- var a3 = a[3] | 0;
- var al3 = a3 & 0x1fff;
- var ah3 = a3 >>> 13;
- var a4 = a[4] | 0;
- var al4 = a4 & 0x1fff;
- var ah4 = a4 >>> 13;
- var a5 = a[5] | 0;
- var al5 = a5 & 0x1fff;
- var ah5 = a5 >>> 13;
- var a6 = a[6] | 0;
- var al6 = a6 & 0x1fff;
- var ah6 = a6 >>> 13;
- var a7 = a[7] | 0;
- var al7 = a7 & 0x1fff;
- var ah7 = a7 >>> 13;
- var a8 = a[8] | 0;
- var al8 = a8 & 0x1fff;
- var ah8 = a8 >>> 13;
- var a9 = a[9] | 0;
- var al9 = a9 & 0x1fff;
- var ah9 = a9 >>> 13;
- var b0 = b[0] | 0;
- var bl0 = b0 & 0x1fff;
- var bh0 = b0 >>> 13;
- var b1 = b[1] | 0;
- var bl1 = b1 & 0x1fff;
- var bh1 = b1 >>> 13;
- var b2 = b[2] | 0;
- var bl2 = b2 & 0x1fff;
- var bh2 = b2 >>> 13;
- var b3 = b[3] | 0;
- var bl3 = b3 & 0x1fff;
- var bh3 = b3 >>> 13;
- var b4 = b[4] | 0;
- var bl4 = b4 & 0x1fff;
- var bh4 = b4 >>> 13;
- var b5 = b[5] | 0;
- var bl5 = b5 & 0x1fff;
- var bh5 = b5 >>> 13;
- var b6 = b[6] | 0;
- var bl6 = b6 & 0x1fff;
- var bh6 = b6 >>> 13;
- var b7 = b[7] | 0;
- var bl7 = b7 & 0x1fff;
- var bh7 = b7 >>> 13;
- var b8 = b[8] | 0;
- var bl8 = b8 & 0x1fff;
- var bh8 = b8 >>> 13;
- var b9 = b[9] | 0;
- var bl9 = b9 & 0x1fff;
- var bh9 = b9 >>> 13;
+ // there is no animation at the current moment, however
+ // these runner methods will get later updated with the
+ // methods leading into the driver's end/cancel methods
+ // for now they just stop the animation from starting
+ var runner = new $$AnimateRunner({
+ end: function() { close(); },
+ cancel: function() { close(true); }
+ });
- out.negative = self.negative ^ num.negative;
- out.length = 19;
- /* k = 0 */
- lo = Math.imul(al0, bl0);
- mid = Math.imul(al0, bh0);
- mid = (mid + Math.imul(ah0, bl0)) | 0;
- hi = Math.imul(ah0, bh0);
- var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
- w0 &= 0x3ffffff;
- /* k = 1 */
- lo = Math.imul(al1, bl0);
- mid = Math.imul(al1, bh0);
- mid = (mid + Math.imul(ah1, bl0)) | 0;
- hi = Math.imul(ah1, bh0);
- lo = (lo + Math.imul(al0, bl1)) | 0;
- mid = (mid + Math.imul(al0, bh1)) | 0;
- mid = (mid + Math.imul(ah0, bl1)) | 0;
- hi = (hi + Math.imul(ah0, bh1)) | 0;
- var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
- w1 &= 0x3ffffff;
- /* k = 2 */
- lo = Math.imul(al2, bl0);
- mid = Math.imul(al2, bh0);
- mid = (mid + Math.imul(ah2, bl0)) | 0;
- hi = Math.imul(ah2, bh0);
- lo = (lo + Math.imul(al1, bl1)) | 0;
- mid = (mid + Math.imul(al1, bh1)) | 0;
- mid = (mid + Math.imul(ah1, bl1)) | 0;
- hi = (hi + Math.imul(ah1, bh1)) | 0;
- lo = (lo + Math.imul(al0, bl2)) | 0;
- mid = (mid + Math.imul(al0, bh2)) | 0;
- mid = (mid + Math.imul(ah0, bl2)) | 0;
- hi = (hi + Math.imul(ah0, bh2)) | 0;
- var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
- w2 &= 0x3ffffff;
- /* k = 3 */
- lo = Math.imul(al3, bl0);
- mid = Math.imul(al3, bh0);
- mid = (mid + Math.imul(ah3, bl0)) | 0;
- hi = Math.imul(ah3, bh0);
- lo = (lo + Math.imul(al2, bl1)) | 0;
- mid = (mid + Math.imul(al2, bh1)) | 0;
- mid = (mid + Math.imul(ah2, bl1)) | 0;
- hi = (hi + Math.imul(ah2, bh1)) | 0;
- lo = (lo + Math.imul(al1, bl2)) | 0;
- mid = (mid + Math.imul(al1, bh2)) | 0;
- mid = (mid + Math.imul(ah1, bl2)) | 0;
- hi = (hi + Math.imul(ah1, bh2)) | 0;
- lo = (lo + Math.imul(al0, bl3)) | 0;
- mid = (mid + Math.imul(al0, bh3)) | 0;
- mid = (mid + Math.imul(ah0, bl3)) | 0;
- hi = (hi + Math.imul(ah0, bh3)) | 0;
- var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
- w3 &= 0x3ffffff;
- /* k = 4 */
- lo = Math.imul(al4, bl0);
- mid = Math.imul(al4, bh0);
- mid = (mid + Math.imul(ah4, bl0)) | 0;
- hi = Math.imul(ah4, bh0);
- lo = (lo + Math.imul(al3, bl1)) | 0;
- mid = (mid + Math.imul(al3, bh1)) | 0;
- mid = (mid + Math.imul(ah3, bl1)) | 0;
- hi = (hi + Math.imul(ah3, bh1)) | 0;
- lo = (lo + Math.imul(al2, bl2)) | 0;
- mid = (mid + Math.imul(al2, bh2)) | 0;
- mid = (mid + Math.imul(ah2, bl2)) | 0;
- hi = (hi + Math.imul(ah2, bh2)) | 0;
- lo = (lo + Math.imul(al1, bl3)) | 0;
- mid = (mid + Math.imul(al1, bh3)) | 0;
- mid = (mid + Math.imul(ah1, bl3)) | 0;
- hi = (hi + Math.imul(ah1, bh3)) | 0;
- lo = (lo + Math.imul(al0, bl4)) | 0;
- mid = (mid + Math.imul(al0, bh4)) | 0;
- mid = (mid + Math.imul(ah0, bl4)) | 0;
- hi = (hi + Math.imul(ah0, bh4)) | 0;
- var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
- w4 &= 0x3ffffff;
- /* k = 5 */
- lo = Math.imul(al5, bl0);
- mid = Math.imul(al5, bh0);
- mid = (mid + Math.imul(ah5, bl0)) | 0;
- hi = Math.imul(ah5, bh0);
- lo = (lo + Math.imul(al4, bl1)) | 0;
- mid = (mid + Math.imul(al4, bh1)) | 0;
- mid = (mid + Math.imul(ah4, bl1)) | 0;
- hi = (hi + Math.imul(ah4, bh1)) | 0;
- lo = (lo + Math.imul(al3, bl2)) | 0;
- mid = (mid + Math.imul(al3, bh2)) | 0;
- mid = (mid + Math.imul(ah3, bl2)) | 0;
- hi = (hi + Math.imul(ah3, bh2)) | 0;
- lo = (lo + Math.imul(al2, bl3)) | 0;
- mid = (mid + Math.imul(al2, bh3)) | 0;
- mid = (mid + Math.imul(ah2, bl3)) | 0;
- hi = (hi + Math.imul(ah2, bh3)) | 0;
- lo = (lo + Math.imul(al1, bl4)) | 0;
- mid = (mid + Math.imul(al1, bh4)) | 0;
- mid = (mid + Math.imul(ah1, bl4)) | 0;
- hi = (hi + Math.imul(ah1, bh4)) | 0;
- lo = (lo + Math.imul(al0, bl5)) | 0;
- mid = (mid + Math.imul(al0, bh5)) | 0;
- mid = (mid + Math.imul(ah0, bl5)) | 0;
- hi = (hi + Math.imul(ah0, bh5)) | 0;
- var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
- w5 &= 0x3ffffff;
- /* k = 6 */
- lo = Math.imul(al6, bl0);
- mid = Math.imul(al6, bh0);
- mid = (mid + Math.imul(ah6, bl0)) | 0;
- hi = Math.imul(ah6, bh0);
- lo = (lo + Math.imul(al5, bl1)) | 0;
- mid = (mid + Math.imul(al5, bh1)) | 0;
- mid = (mid + Math.imul(ah5, bl1)) | 0;
- hi = (hi + Math.imul(ah5, bh1)) | 0;
- lo = (lo + Math.imul(al4, bl2)) | 0;
- mid = (mid + Math.imul(al4, bh2)) | 0;
- mid = (mid + Math.imul(ah4, bl2)) | 0;
- hi = (hi + Math.imul(ah4, bh2)) | 0;
- lo = (lo + Math.imul(al3, bl3)) | 0;
- mid = (mid + Math.imul(al3, bh3)) | 0;
- mid = (mid + Math.imul(ah3, bl3)) | 0;
- hi = (hi + Math.imul(ah3, bh3)) | 0;
- lo = (lo + Math.imul(al2, bl4)) | 0;
- mid = (mid + Math.imul(al2, bh4)) | 0;
- mid = (mid + Math.imul(ah2, bl4)) | 0;
- hi = (hi + Math.imul(ah2, bh4)) | 0;
- lo = (lo + Math.imul(al1, bl5)) | 0;
- mid = (mid + Math.imul(al1, bh5)) | 0;
- mid = (mid + Math.imul(ah1, bl5)) | 0;
- hi = (hi + Math.imul(ah1, bh5)) | 0;
- lo = (lo + Math.imul(al0, bl6)) | 0;
- mid = (mid + Math.imul(al0, bh6)) | 0;
- mid = (mid + Math.imul(ah0, bl6)) | 0;
- hi = (hi + Math.imul(ah0, bh6)) | 0;
- var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
- w6 &= 0x3ffffff;
- /* k = 7 */
- lo = Math.imul(al7, bl0);
- mid = Math.imul(al7, bh0);
- mid = (mid + Math.imul(ah7, bl0)) | 0;
- hi = Math.imul(ah7, bh0);
- lo = (lo + Math.imul(al6, bl1)) | 0;
- mid = (mid + Math.imul(al6, bh1)) | 0;
- mid = (mid + Math.imul(ah6, bl1)) | 0;
- hi = (hi + Math.imul(ah6, bh1)) | 0;
- lo = (lo + Math.imul(al5, bl2)) | 0;
- mid = (mid + Math.imul(al5, bh2)) | 0;
- mid = (mid + Math.imul(ah5, bl2)) | 0;
- hi = (hi + Math.imul(ah5, bh2)) | 0;
- lo = (lo + Math.imul(al4, bl3)) | 0;
- mid = (mid + Math.imul(al4, bh3)) | 0;
- mid = (mid + Math.imul(ah4, bl3)) | 0;
- hi = (hi + Math.imul(ah4, bh3)) | 0;
- lo = (lo + Math.imul(al3, bl4)) | 0;
- mid = (mid + Math.imul(al3, bh4)) | 0;
- mid = (mid + Math.imul(ah3, bl4)) | 0;
- hi = (hi + Math.imul(ah3, bh4)) | 0;
- lo = (lo + Math.imul(al2, bl5)) | 0;
- mid = (mid + Math.imul(al2, bh5)) | 0;
- mid = (mid + Math.imul(ah2, bl5)) | 0;
- hi = (hi + Math.imul(ah2, bh5)) | 0;
- lo = (lo + Math.imul(al1, bl6)) | 0;
- mid = (mid + Math.imul(al1, bh6)) | 0;
- mid = (mid + Math.imul(ah1, bl6)) | 0;
- hi = (hi + Math.imul(ah1, bh6)) | 0;
- lo = (lo + Math.imul(al0, bl7)) | 0;
- mid = (mid + Math.imul(al0, bh7)) | 0;
- mid = (mid + Math.imul(ah0, bl7)) | 0;
- hi = (hi + Math.imul(ah0, bh7)) | 0;
- var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
- w7 &= 0x3ffffff;
- /* k = 8 */
- lo = Math.imul(al8, bl0);
- mid = Math.imul(al8, bh0);
- mid = (mid + Math.imul(ah8, bl0)) | 0;
- hi = Math.imul(ah8, bh0);
- lo = (lo + Math.imul(al7, bl1)) | 0;
- mid = (mid + Math.imul(al7, bh1)) | 0;
- mid = (mid + Math.imul(ah7, bl1)) | 0;
- hi = (hi + Math.imul(ah7, bh1)) | 0;
- lo = (lo + Math.imul(al6, bl2)) | 0;
- mid = (mid + Math.imul(al6, bh2)) | 0;
- mid = (mid + Math.imul(ah6, bl2)) | 0;
- hi = (hi + Math.imul(ah6, bh2)) | 0;
- lo = (lo + Math.imul(al5, bl3)) | 0;
- mid = (mid + Math.imul(al5, bh3)) | 0;
- mid = (mid + Math.imul(ah5, bl3)) | 0;
- hi = (hi + Math.imul(ah5, bh3)) | 0;
- lo = (lo + Math.imul(al4, bl4)) | 0;
- mid = (mid + Math.imul(al4, bh4)) | 0;
- mid = (mid + Math.imul(ah4, bl4)) | 0;
- hi = (hi + Math.imul(ah4, bh4)) | 0;
- lo = (lo + Math.imul(al3, bl5)) | 0;
- mid = (mid + Math.imul(al3, bh5)) | 0;
- mid = (mid + Math.imul(ah3, bl5)) | 0;
- hi = (hi + Math.imul(ah3, bh5)) | 0;
- lo = (lo + Math.imul(al2, bl6)) | 0;
- mid = (mid + Math.imul(al2, bh6)) | 0;
- mid = (mid + Math.imul(ah2, bl6)) | 0;
- hi = (hi + Math.imul(ah2, bh6)) | 0;
- lo = (lo + Math.imul(al1, bl7)) | 0;
- mid = (mid + Math.imul(al1, bh7)) | 0;
- mid = (mid + Math.imul(ah1, bl7)) | 0;
- hi = (hi + Math.imul(ah1, bh7)) | 0;
- lo = (lo + Math.imul(al0, bl8)) | 0;
- mid = (mid + Math.imul(al0, bh8)) | 0;
- mid = (mid + Math.imul(ah0, bl8)) | 0;
- hi = (hi + Math.imul(ah0, bh8)) | 0;
- var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
- w8 &= 0x3ffffff;
- /* k = 9 */
- lo = Math.imul(al9, bl0);
- mid = Math.imul(al9, bh0);
- mid = (mid + Math.imul(ah9, bl0)) | 0;
- hi = Math.imul(ah9, bh0);
- lo = (lo + Math.imul(al8, bl1)) | 0;
- mid = (mid + Math.imul(al8, bh1)) | 0;
- mid = (mid + Math.imul(ah8, bl1)) | 0;
- hi = (hi + Math.imul(ah8, bh1)) | 0;
- lo = (lo + Math.imul(al7, bl2)) | 0;
- mid = (mid + Math.imul(al7, bh2)) | 0;
- mid = (mid + Math.imul(ah7, bl2)) | 0;
- hi = (hi + Math.imul(ah7, bh2)) | 0;
- lo = (lo + Math.imul(al6, bl3)) | 0;
- mid = (mid + Math.imul(al6, bh3)) | 0;
- mid = (mid + Math.imul(ah6, bl3)) | 0;
- hi = (hi + Math.imul(ah6, bh3)) | 0;
- lo = (lo + Math.imul(al5, bl4)) | 0;
- mid = (mid + Math.imul(al5, bh4)) | 0;
- mid = (mid + Math.imul(ah5, bl4)) | 0;
- hi = (hi + Math.imul(ah5, bh4)) | 0;
- lo = (lo + Math.imul(al4, bl5)) | 0;
- mid = (mid + Math.imul(al4, bh5)) | 0;
- mid = (mid + Math.imul(ah4, bl5)) | 0;
- hi = (hi + Math.imul(ah4, bh5)) | 0;
- lo = (lo + Math.imul(al3, bl6)) | 0;
- mid = (mid + Math.imul(al3, bh6)) | 0;
- mid = (mid + Math.imul(ah3, bl6)) | 0;
- hi = (hi + Math.imul(ah3, bh6)) | 0;
- lo = (lo + Math.imul(al2, bl7)) | 0;
- mid = (mid + Math.imul(al2, bh7)) | 0;
- mid = (mid + Math.imul(ah2, bl7)) | 0;
- hi = (hi + Math.imul(ah2, bh7)) | 0;
- lo = (lo + Math.imul(al1, bl8)) | 0;
- mid = (mid + Math.imul(al1, bh8)) | 0;
- mid = (mid + Math.imul(ah1, bl8)) | 0;
- hi = (hi + Math.imul(ah1, bh8)) | 0;
- lo = (lo + Math.imul(al0, bl9)) | 0;
- mid = (mid + Math.imul(al0, bh9)) | 0;
- mid = (mid + Math.imul(ah0, bl9)) | 0;
- hi = (hi + Math.imul(ah0, bh9)) | 0;
- var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
- w9 &= 0x3ffffff;
- /* k = 10 */
- lo = Math.imul(al9, bl1);
- mid = Math.imul(al9, bh1);
- mid = (mid + Math.imul(ah9, bl1)) | 0;
- hi = Math.imul(ah9, bh1);
- lo = (lo + Math.imul(al8, bl2)) | 0;
- mid = (mid + Math.imul(al8, bh2)) | 0;
- mid = (mid + Math.imul(ah8, bl2)) | 0;
- hi = (hi + Math.imul(ah8, bh2)) | 0;
- lo = (lo + Math.imul(al7, bl3)) | 0;
- mid = (mid + Math.imul(al7, bh3)) | 0;
- mid = (mid + Math.imul(ah7, bl3)) | 0;
- hi = (hi + Math.imul(ah7, bh3)) | 0;
- lo = (lo + Math.imul(al6, bl4)) | 0;
- mid = (mid + Math.imul(al6, bh4)) | 0;
- mid = (mid + Math.imul(ah6, bl4)) | 0;
- hi = (hi + Math.imul(ah6, bh4)) | 0;
- lo = (lo + Math.imul(al5, bl5)) | 0;
- mid = (mid + Math.imul(al5, bh5)) | 0;
- mid = (mid + Math.imul(ah5, bl5)) | 0;
- hi = (hi + Math.imul(ah5, bh5)) | 0;
- lo = (lo + Math.imul(al4, bl6)) | 0;
- mid = (mid + Math.imul(al4, bh6)) | 0;
- mid = (mid + Math.imul(ah4, bl6)) | 0;
- hi = (hi + Math.imul(ah4, bh6)) | 0;
- lo = (lo + Math.imul(al3, bl7)) | 0;
- mid = (mid + Math.imul(al3, bh7)) | 0;
- mid = (mid + Math.imul(ah3, bl7)) | 0;
- hi = (hi + Math.imul(ah3, bh7)) | 0;
- lo = (lo + Math.imul(al2, bl8)) | 0;
- mid = (mid + Math.imul(al2, bh8)) | 0;
- mid = (mid + Math.imul(ah2, bl8)) | 0;
- hi = (hi + Math.imul(ah2, bh8)) | 0;
- lo = (lo + Math.imul(al1, bl9)) | 0;
- mid = (mid + Math.imul(al1, bh9)) | 0;
- mid = (mid + Math.imul(ah1, bl9)) | 0;
- hi = (hi + Math.imul(ah1, bh9)) | 0;
- var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
- w10 &= 0x3ffffff;
- /* k = 11 */
- lo = Math.imul(al9, bl2);
- mid = Math.imul(al9, bh2);
- mid = (mid + Math.imul(ah9, bl2)) | 0;
- hi = Math.imul(ah9, bh2);
- lo = (lo + Math.imul(al8, bl3)) | 0;
- mid = (mid + Math.imul(al8, bh3)) | 0;
- mid = (mid + Math.imul(ah8, bl3)) | 0;
- hi = (hi + Math.imul(ah8, bh3)) | 0;
- lo = (lo + Math.imul(al7, bl4)) | 0;
- mid = (mid + Math.imul(al7, bh4)) | 0;
- mid = (mid + Math.imul(ah7, bl4)) | 0;
- hi = (hi + Math.imul(ah7, bh4)) | 0;
- lo = (lo + Math.imul(al6, bl5)) | 0;
- mid = (mid + Math.imul(al6, bh5)) | 0;
- mid = (mid + Math.imul(ah6, bl5)) | 0;
- hi = (hi + Math.imul(ah6, bh5)) | 0;
- lo = (lo + Math.imul(al5, bl6)) | 0;
- mid = (mid + Math.imul(al5, bh6)) | 0;
- mid = (mid + Math.imul(ah5, bl6)) | 0;
- hi = (hi + Math.imul(ah5, bh6)) | 0;
- lo = (lo + Math.imul(al4, bl7)) | 0;
- mid = (mid + Math.imul(al4, bh7)) | 0;
- mid = (mid + Math.imul(ah4, bl7)) | 0;
- hi = (hi + Math.imul(ah4, bh7)) | 0;
- lo = (lo + Math.imul(al3, bl8)) | 0;
- mid = (mid + Math.imul(al3, bh8)) | 0;
- mid = (mid + Math.imul(ah3, bl8)) | 0;
- hi = (hi + Math.imul(ah3, bh8)) | 0;
- lo = (lo + Math.imul(al2, bl9)) | 0;
- mid = (mid + Math.imul(al2, bh9)) | 0;
- mid = (mid + Math.imul(ah2, bl9)) | 0;
- hi = (hi + Math.imul(ah2, bh9)) | 0;
- var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
- w11 &= 0x3ffffff;
- /* k = 12 */
- lo = Math.imul(al9, bl3);
- mid = Math.imul(al9, bh3);
- mid = (mid + Math.imul(ah9, bl3)) | 0;
- hi = Math.imul(ah9, bh3);
- lo = (lo + Math.imul(al8, bl4)) | 0;
- mid = (mid + Math.imul(al8, bh4)) | 0;
- mid = (mid + Math.imul(ah8, bl4)) | 0;
- hi = (hi + Math.imul(ah8, bh4)) | 0;
- lo = (lo + Math.imul(al7, bl5)) | 0;
- mid = (mid + Math.imul(al7, bh5)) | 0;
- mid = (mid + Math.imul(ah7, bl5)) | 0;
- hi = (hi + Math.imul(ah7, bh5)) | 0;
- lo = (lo + Math.imul(al6, bl6)) | 0;
- mid = (mid + Math.imul(al6, bh6)) | 0;
- mid = (mid + Math.imul(ah6, bl6)) | 0;
- hi = (hi + Math.imul(ah6, bh6)) | 0;
- lo = (lo + Math.imul(al5, bl7)) | 0;
- mid = (mid + Math.imul(al5, bh7)) | 0;
- mid = (mid + Math.imul(ah5, bl7)) | 0;
- hi = (hi + Math.imul(ah5, bh7)) | 0;
- lo = (lo + Math.imul(al4, bl8)) | 0;
- mid = (mid + Math.imul(al4, bh8)) | 0;
- mid = (mid + Math.imul(ah4, bl8)) | 0;
- hi = (hi + Math.imul(ah4, bh8)) | 0;
- lo = (lo + Math.imul(al3, bl9)) | 0;
- mid = (mid + Math.imul(al3, bh9)) | 0;
- mid = (mid + Math.imul(ah3, bl9)) | 0;
- hi = (hi + Math.imul(ah3, bh9)) | 0;
- var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
- w12 &= 0x3ffffff;
- /* k = 13 */
- lo = Math.imul(al9, bl4);
- mid = Math.imul(al9, bh4);
- mid = (mid + Math.imul(ah9, bl4)) | 0;
- hi = Math.imul(ah9, bh4);
- lo = (lo + Math.imul(al8, bl5)) | 0;
- mid = (mid + Math.imul(al8, bh5)) | 0;
- mid = (mid + Math.imul(ah8, bl5)) | 0;
- hi = (hi + Math.imul(ah8, bh5)) | 0;
- lo = (lo + Math.imul(al7, bl6)) | 0;
- mid = (mid + Math.imul(al7, bh6)) | 0;
- mid = (mid + Math.imul(ah7, bl6)) | 0;
- hi = (hi + Math.imul(ah7, bh6)) | 0;
- lo = (lo + Math.imul(al6, bl7)) | 0;
- mid = (mid + Math.imul(al6, bh7)) | 0;
- mid = (mid + Math.imul(ah6, bl7)) | 0;
- hi = (hi + Math.imul(ah6, bh7)) | 0;
- lo = (lo + Math.imul(al5, bl8)) | 0;
- mid = (mid + Math.imul(al5, bh8)) | 0;
- mid = (mid + Math.imul(ah5, bl8)) | 0;
- hi = (hi + Math.imul(ah5, bh8)) | 0;
- lo = (lo + Math.imul(al4, bl9)) | 0;
- mid = (mid + Math.imul(al4, bh9)) | 0;
- mid = (mid + Math.imul(ah4, bl9)) | 0;
- hi = (hi + Math.imul(ah4, bh9)) | 0;
- var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
- w13 &= 0x3ffffff;
- /* k = 14 */
- lo = Math.imul(al9, bl5);
- mid = Math.imul(al9, bh5);
- mid = (mid + Math.imul(ah9, bl5)) | 0;
- hi = Math.imul(ah9, bh5);
- lo = (lo + Math.imul(al8, bl6)) | 0;
- mid = (mid + Math.imul(al8, bh6)) | 0;
- mid = (mid + Math.imul(ah8, bl6)) | 0;
- hi = (hi + Math.imul(ah8, bh6)) | 0;
- lo = (lo + Math.imul(al7, bl7)) | 0;
- mid = (mid + Math.imul(al7, bh7)) | 0;
- mid = (mid + Math.imul(ah7, bl7)) | 0;
- hi = (hi + Math.imul(ah7, bh7)) | 0;
- lo = (lo + Math.imul(al6, bl8)) | 0;
- mid = (mid + Math.imul(al6, bh8)) | 0;
- mid = (mid + Math.imul(ah6, bl8)) | 0;
- hi = (hi + Math.imul(ah6, bh8)) | 0;
- lo = (lo + Math.imul(al5, bl9)) | 0;
- mid = (mid + Math.imul(al5, bh9)) | 0;
- mid = (mid + Math.imul(ah5, bl9)) | 0;
- hi = (hi + Math.imul(ah5, bh9)) | 0;
- var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
- w14 &= 0x3ffffff;
- /* k = 15 */
- lo = Math.imul(al9, bl6);
- mid = Math.imul(al9, bh6);
- mid = (mid + Math.imul(ah9, bl6)) | 0;
- hi = Math.imul(ah9, bh6);
- lo = (lo + Math.imul(al8, bl7)) | 0;
- mid = (mid + Math.imul(al8, bh7)) | 0;
- mid = (mid + Math.imul(ah8, bl7)) | 0;
- hi = (hi + Math.imul(ah8, bh7)) | 0;
- lo = (lo + Math.imul(al7, bl8)) | 0;
- mid = (mid + Math.imul(al7, bh8)) | 0;
- mid = (mid + Math.imul(ah7, bl8)) | 0;
- hi = (hi + Math.imul(ah7, bh8)) | 0;
- lo = (lo + Math.imul(al6, bl9)) | 0;
- mid = (mid + Math.imul(al6, bh9)) | 0;
- mid = (mid + Math.imul(ah6, bl9)) | 0;
- hi = (hi + Math.imul(ah6, bh9)) | 0;
- var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
- w15 &= 0x3ffffff;
- /* k = 16 */
- lo = Math.imul(al9, bl7);
- mid = Math.imul(al9, bh7);
- mid = (mid + Math.imul(ah9, bl7)) | 0;
- hi = Math.imul(ah9, bh7);
- lo = (lo + Math.imul(al8, bl8)) | 0;
- mid = (mid + Math.imul(al8, bh8)) | 0;
- mid = (mid + Math.imul(ah8, bl8)) | 0;
- hi = (hi + Math.imul(ah8, bh8)) | 0;
- lo = (lo + Math.imul(al7, bl9)) | 0;
- mid = (mid + Math.imul(al7, bh9)) | 0;
- mid = (mid + Math.imul(ah7, bl9)) | 0;
- hi = (hi + Math.imul(ah7, bh9)) | 0;
- var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
- w16 &= 0x3ffffff;
- /* k = 17 */
- lo = Math.imul(al9, bl8);
- mid = Math.imul(al9, bh8);
- mid = (mid + Math.imul(ah9, bl8)) | 0;
- hi = Math.imul(ah9, bh8);
- lo = (lo + Math.imul(al8, bl9)) | 0;
- mid = (mid + Math.imul(al8, bh9)) | 0;
- mid = (mid + Math.imul(ah8, bl9)) | 0;
- hi = (hi + Math.imul(ah8, bh9)) | 0;
- var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
- w17 &= 0x3ffffff;
- /* k = 18 */
- lo = Math.imul(al9, bl9);
- mid = Math.imul(al9, bh9);
- mid = (mid + Math.imul(ah9, bl9)) | 0;
- hi = Math.imul(ah9, bh9);
- var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
- c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
- w18 &= 0x3ffffff;
- o[0] = w0;
- o[1] = w1;
- o[2] = w2;
- o[3] = w3;
- o[4] = w4;
- o[5] = w5;
- o[6] = w6;
- o[7] = w7;
- o[8] = w8;
- o[9] = w9;
- o[10] = w10;
- o[11] = w11;
- o[12] = w12;
- o[13] = w13;
- o[14] = w14;
- o[15] = w15;
- o[16] = w16;
- o[17] = w17;
- o[18] = w18;
- if (c !== 0) {
- o[19] = c;
- out.length++;
- }
- return out;
- };
-
- // Polyfill comb
- if (!Math.imul) {
- comb10MulTo = smallMulTo;
- }
-
- function bigMulTo (self, num, out) {
- out.negative = num.negative ^ self.negative;
- out.length = self.length + num.length;
-
- var carry = 0;
- var hncarry = 0;
- for (var k = 0; k < out.length - 1; k++) {
- // Sum all words with the same `i + j = k` and accumulate `ncarry`,
- // note that ncarry could be >= 0x3ffffff
- var ncarry = hncarry;
- hncarry = 0;
- var rword = carry & 0x3ffffff;
- var maxJ = Math.min(k, num.length - 1);
- for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
- var i = k - j;
- var a = self.words[i] | 0;
- var b = num.words[j] | 0;
- var r = a * b;
-
- var lo = r & 0x3ffffff;
- ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
- lo = (lo + rword) | 0;
- rword = lo & 0x3ffffff;
- ncarry = (ncarry + (lo >>> 26)) | 0;
-
- hncarry += ncarry >>> 26;
- ncarry &= 0x3ffffff;
+ if (!drivers.length) {
+ close();
+ return runner;
}
- out.words[k] = rword;
- carry = ncarry;
- ncarry = hncarry;
- }
- if (carry !== 0) {
- out.words[k] = carry;
- } else {
- out.length--;
- }
-
- return out.strip();
- }
-
- function jumboMulTo (self, num, out) {
- var fftm = new FFTM();
- return fftm.mulp(self, num, out);
- }
-
- BN.prototype.mulTo = function mulTo (num, out) {
- var res;
- var len = this.length + num.length;
- if (this.length === 10 && num.length === 10) {
- res = comb10MulTo(this, num, out);
- } else if (len < 63) {
- res = smallMulTo(this, num, out);
- } else if (len < 1024) {
- res = bigMulTo(this, num, out);
- } else {
- res = jumboMulTo(this, num, out);
- }
- return res;
- };
+ var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
+ var tempClasses = options.tempClasses;
+ if (tempClasses) {
+ classes += ' ' + tempClasses;
+ options.tempClasses = null;
+ }
- // Cooley-Tukey algorithm for FFT
- // slightly revisited to rely on looping instead of recursion
+ if (isStructural) {
+ element.data(PREPARE_CLASSES_KEY, 'ng-' + event + PREPARE_CLASS_SUFFIX);
+ }
- function FFTM (x, y) {
- this.x = x;
- this.y = y;
- }
+ setRunner(element, runner);
- FFTM.prototype.makeRBT = function makeRBT (N) {
- var t = new Array(N);
- var l = BN.prototype._countBits(N) - 1;
- for (var i = 0; i < N; i++) {
- t[i] = this.revBin(i, l, N);
- }
+ animationQueue.push({
+ // this data is used by the postDigest code and passed into
+ // the driver step function
+ element: element,
+ classes: classes,
+ event: event,
+ structural: isStructural,
+ options: options,
+ beforeStart: beforeStart,
+ close: close
+ });
- return t;
- };
+ element.on('$destroy', handleDestroyedElement);
- // Returns binary-reversed representation of `x`
- FFTM.prototype.revBin = function revBin (x, l, N) {
- if (x === 0 || x === N - 1) return x;
+ // we only want there to be one function called within the post digest
+ // block. This way we can group animations for all the animations that
+ // were apart of the same postDigest flush call.
+ if (animationQueue.length > 1) return runner;
- var rb = 0;
- for (var i = 0; i < l; i++) {
- rb |= (x & 1) << (l - i - 1);
- x >>= 1;
- }
+ $rootScope.$$postDigest(function() {
+ var animations = [];
+ forEach(animationQueue, function(entry) {
+ // the element was destroyed early on which removed the runner
+ // form its storage. This means we can't animate this element
+ // at all and it already has been closed due to destruction.
+ if (getRunner(entry.element)) {
+ animations.push(entry);
+ } else {
+ entry.close();
+ }
+ });
- return rb;
- };
+ // now any future animations will be in another postDigest
+ animationQueue.length = 0;
- // Performs "tweedling" phase, therefore 'emulating'
- // behaviour of the recursive algorithm
- FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
- for (var i = 0; i < N; i++) {
- rtws[i] = rws[rbt[i]];
- itws[i] = iws[rbt[i]];
- }
- };
+ var groupedAnimations = groupAnimations(animations);
+ var toBeSortedAnimations = [];
- FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
- this.permute(rbt, rws, iws, rtws, itws, N);
+ forEach(groupedAnimations, function(animationEntry) {
+ var element = animationEntry.from ? animationEntry.from.element : animationEntry.element;
+ var extraClasses = options.addClass;
- for (var s = 1; s < N; s <<= 1) {
- var l = s << 1;
+ extraClasses = (extraClasses ? (extraClasses + ' ') : '') + NG_ANIMATE_CLASSNAME;
+ var cacheKey = $$animateCache.cacheKey(element[0], animationEntry.event, extraClasses, options.removeClass);
- var rtwdf = Math.cos(2 * Math.PI / l);
- var itwdf = Math.sin(2 * Math.PI / l);
+ toBeSortedAnimations.push({
+ element: element,
+ domNode: getDomNode(element),
+ fn: function triggerAnimationStart() {
+ var startAnimationFn, closeFn = animationEntry.close;
- for (var p = 0; p < N; p += l) {
- var rtwdf_ = rtwdf;
- var itwdf_ = itwdf;
+ // 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;
+ }
- for (var j = 0; j < s; j++) {
- var re = rtws[p + j];
- var ie = itws[p + j];
+ // 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 ro = rtws[p + j + s];
- var io = itws[p + j + s];
+ // 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;
- var rx = rtwdf_ * ro - itwdf_ * io;
+ if (getRunner(targetElement)) {
+ var operation = invokeFirstDriver(animationEntry);
+ if (operation) {
+ startAnimationFn = operation.start;
+ }
+ }
- io = rtwdf_ * io + itwdf_ * ro;
- ro = rx;
+ if (!startAnimationFn) {
+ closeFn();
+ } else {
+ var animationRunner = startAnimationFn();
+ animationRunner.done(function(status) {
+ closeFn(!status);
+ });
+ updateAnimationRunners(animationEntry, animationRunner);
+ }
+ }
+ });
+ });
- rtws[p + j] = re + ro;
- itws[p + j] = ie + io;
+ // 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.
+ 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;
- rtws[p + j + s] = re - ro;
- itws[p + j + s] = ie - io;
+ // the RAFScheduler code only uses functions
+ finalAnimations[i][j] = entry.fn;
- /* jshint maxdepth : false */
- if (j !== l) {
- rx = rtwdf * rtwdf_ - itwdf * itwdf_;
+ // 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;
+ }
- itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
- rtwdf_ = rx;
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
+ if (prepareClassName) {
+ $$jqLite.addClass(element, prepareClassName);
+ }
}
}
- }
- }
- };
-
- FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
- var N = Math.max(m, n) | 1;
- var odd = N & 1;
- var i = 0;
- for (N = N / 2 | 0; N; N = N >>> 1) {
- i++;
- }
-
- return 1 << i + 1 + odd;
- };
-
- FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
- if (N <= 1) return;
-
- for (var i = 0; i < N / 2; i++) {
- var t = rws[i];
-
- rws[i] = rws[N - i - 1];
- rws[N - i - 1] = t;
- t = iws[i];
-
- iws[i] = -iws[N - i - 1];
- iws[N - i - 1] = -t;
- }
- };
-
- FFTM.prototype.normalize13b = function normalize13b (ws, N) {
- var carry = 0;
- for (var i = 0; i < N / 2; i++) {
- var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
- Math.round(ws[2 * i] / N) +
- carry;
+ $$rAFScheduler(finalAnimations);
+ });
- ws[i] = w & 0x3ffffff;
+ return runner;
- if (w < 0x4000000) {
- carry = 0;
- } else {
- carry = w / 0x4000000 | 0;
+ // TODO(matsko): change to reference nodes
+ function getAnchorNodes(node) {
+ var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']';
+ var items = node.hasAttribute(NG_ANIMATE_REF_ATTR)
+ ? [node]
+ : node.querySelectorAll(SELECTOR);
+ var anchors = [];
+ forEach(items, function(node) {
+ var attr = node.getAttribute(NG_ANIMATE_REF_ATTR);
+ if (attr && attr.length) {
+ anchors.push(node);
+ }
+ });
+ return anchors;
}
- }
-
- return ws;
- };
-
- FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
- var carry = 0;
- for (var i = 0; i < len; i++) {
- carry = carry + (ws[i] | 0);
-
- rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
- rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
- }
-
- // Pad with zeroes
- for (i = 2 * len; i < N; ++i) {
- rws[i] = 0;
- }
-
- assert(carry === 0);
- assert((carry & ~0x1fff) === 0);
- };
-
- FFTM.prototype.stub = function stub (N) {
- var ph = new Array(N);
- for (var i = 0; i < N; i++) {
- ph[i] = 0;
- }
-
- return ph;
- };
-
- FFTM.prototype.mulp = function mulp (x, y, out) {
- var N = 2 * this.guessLen13b(x.length, y.length);
-
- var rbt = this.makeRBT(N);
-
- var _ = this.stub(N);
-
- var rws = new Array(N);
- var rwst = new Array(N);
- var iwst = new Array(N);
-
- var nrws = new Array(N);
- var nrwst = new Array(N);
- var niwst = new Array(N);
-
- var rmws = out.words;
- rmws.length = N;
-
- this.convert13b(x.words, x.length, rws, N);
- this.convert13b(y.words, y.length, nrws, N);
-
- this.transform(rws, _, rwst, iwst, N, rbt);
- this.transform(nrws, _, nrwst, niwst, N, rbt);
-
- for (var i = 0; i < N; i++) {
- var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
- iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
- rwst[i] = rx;
- }
-
- this.conjugate(rwst, iwst, N);
- this.transform(rwst, iwst, rmws, _, N, rbt);
- this.conjugate(rmws, _, N);
- this.normalize13b(rmws, N);
-
- out.negative = x.negative ^ y.negative;
- out.length = x.length + y.length;
- return out.strip();
- };
-
- // Multiply `this` by `num`
- BN.prototype.mul = function mul (num) {
- var out = new BN(null);
- out.words = new Array(this.length + num.length);
- return this.mulTo(num, out);
- };
-
- // Multiply employing FFT
- BN.prototype.mulf = function mulf (num) {
- var out = new BN(null);
- out.words = new Array(this.length + num.length);
- return jumboMulTo(this, num, out);
- };
-
- // In-place Multiplication
- BN.prototype.imul = function imul (num) {
- return this.clone().mulTo(num, this);
- };
-
- BN.prototype.imuln = function imuln (num) {
- assert(typeof num === 'number');
- assert(num < 0x4000000);
-
- // Carry
- var carry = 0;
- for (var i = 0; i < this.length; i++) {
- var w = (this.words[i] | 0) * num;
- var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
- carry >>= 26;
- carry += (w / 0x4000000) | 0;
- // NOTE: lo is 27bit maximum
- carry += lo >>> 26;
- this.words[i] = lo & 0x3ffffff;
- }
- if (carry !== 0) {
- this.words[i] = carry;
- this.length++;
- }
+ function groupAnimations(animations) {
+ var preparedAnimations = [];
+ var refLookup = {};
+ forEach(animations, function(animation, index) {
+ var element = animation.element;
+ var node = getDomNode(element);
+ var event = animation.event;
+ var enterOrMove = ['enter', 'move'].indexOf(event) >= 0;
+ var anchorNodes = animation.structural ? getAnchorNodes(node) : [];
- return this;
- };
+ if (anchorNodes.length) {
+ var direction = enterOrMove ? 'to' : 'from';
- BN.prototype.muln = function muln (num) {
- return this.clone().imuln(num);
- };
+ forEach(anchorNodes, function(anchor) {
+ var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR);
+ refLookup[key] = refLookup[key] || {};
+ refLookup[key][direction] = {
+ animationID: index,
+ element: jqLite(anchor)
+ };
+ });
+ } else {
+ preparedAnimations.push(animation);
+ }
+ });
- // `this` * `this`
- BN.prototype.sqr = function sqr () {
- return this.mul(this);
- };
+ var usedIndicesLookup = {};
+ var anchorGroups = {};
+ forEach(refLookup, function(operations, key) {
+ var from = operations.from;
+ var to = operations.to;
- // `this` * `this` in-place
- BN.prototype.isqr = function isqr () {
- return this.imul(this.clone());
- };
+ if (!from || !to) {
+ // only one of these is set therefore we can't have an
+ // anchor animation since all three pieces are required
+ var index = from ? from.animationID : to.animationID;
+ var indexKey = index.toString();
+ if (!usedIndicesLookup[indexKey]) {
+ usedIndicesLookup[indexKey] = true;
+ preparedAnimations.push(animations[index]);
+ }
+ return;
+ }
- // Math.pow(`this`, `num`)
- BN.prototype.pow = function pow (num) {
- var w = toBitArray(num);
- if (w.length === 0) return new BN(1);
+ var fromAnimation = animations[from.animationID];
+ var toAnimation = animations[to.animationID];
+ var lookupKey = from.animationID.toString();
+ if (!anchorGroups[lookupKey]) {
+ var group = anchorGroups[lookupKey] = {
+ structural: true,
+ beforeStart: function() {
+ fromAnimation.beforeStart();
+ toAnimation.beforeStart();
+ },
+ close: function() {
+ fromAnimation.close();
+ toAnimation.close();
+ },
+ classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes),
+ from: fromAnimation,
+ to: toAnimation,
+ anchors: [] // TODO(matsko): change to reference nodes
+ };
- // Skip leading zeroes
- var res = this;
- for (var i = 0; i < w.length; i++, res = res.sqr()) {
- if (w[i] !== 0) break;
- }
+ // the anchor animations require that the from and to elements both have at least
+ // one shared CSS class which effectively marries the two elements together to use
+ // the same animation driver and to properly sequence the anchor animation.
+ if (group.classes.length) {
+ preparedAnimations.push(group);
+ } else {
+ preparedAnimations.push(fromAnimation);
+ preparedAnimations.push(toAnimation);
+ }
+ }
- if (++i < w.length) {
- for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
- if (w[i] === 0) continue;
+ anchorGroups[lookupKey].anchors.push({
+ 'out': from.element, 'in': to.element
+ });
+ });
- res = res.mul(q);
+ return preparedAnimations;
}
- }
- return res;
- };
+ function cssClassesIntersection(a,b) {
+ a = a.split(' ');
+ b = b.split(' ');
+ var matches = [];
- // Shift-left in-place
- BN.prototype.iushln = function iushln (bits) {
- assert(typeof bits === 'number' && bits >= 0);
- var r = bits % 26;
- var s = (bits - r) / 26;
- var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
- var i;
+ for (var i = 0; i < a.length; i++) {
+ var aa = a[i];
+ if (aa.substring(0,3) === 'ng-') continue;
- if (r !== 0) {
- var carry = 0;
+ for (var j = 0; j < b.length; j++) {
+ if (aa === b[j]) {
+ matches.push(aa);
+ break;
+ }
+ }
+ }
- for (i = 0; i < this.length; i++) {
- var newCarry = this.words[i] & carryMask;
- var c = ((this.words[i] | 0) - newCarry) << r;
- this.words[i] = c | carry;
- carry = newCarry >>> (26 - r);
+ return matches.join(' ');
}
- if (carry) {
- this.words[i] = carry;
- this.length++;
+ function invokeFirstDriver(animationDetails) {
+ // we loop in reverse order since the more general drivers (like CSS and JS)
+ // may attempt more elements, but custom drivers are more particular
+ for (var i = drivers.length - 1; i >= 0; i--) {
+ var driverName = drivers[i];
+ var factory = $injector.get(driverName);
+ var driver = factory(animationDetails);
+ if (driver) {
+ return driver;
+ }
+ }
}
- }
- if (s !== 0) {
- for (i = this.length - 1; i >= 0; i--) {
- this.words[i + s] = this.words[i];
- }
+ function beforeStart() {
+ tempClasses = (tempClasses ? (tempClasses + ' ') : '') + NG_ANIMATE_CLASSNAME;
+ $$jqLite.addClass(element, tempClasses);
- for (i = 0; i < s; i++) {
- this.words[i] = 0;
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
+ if (prepareClassName) {
+ $$jqLite.removeClass(element, prepareClassName);
+ prepareClassName = null;
+ }
}
- this.length += s;
- }
-
- return this.strip();
- };
-
- BN.prototype.ishln = function ishln (bits) {
- // TODO(indutny): implement me
- assert(this.negative === 0);
- return this.iushln(bits);
- };
-
- // Shift-right in-place
- // NOTE: `hint` is a lowest bit before trailing zeroes
- // NOTE: if `extended` is present - it will be filled with destroyed bits
- BN.prototype.iushrn = function iushrn (bits, hint, extended) {
- assert(typeof bits === 'number' && bits >= 0);
- var h;
- if (hint) {
- h = (hint - (hint % 26)) / 26;
- } else {
- h = 0;
- }
-
- var r = bits % 26;
- var s = Math.min((bits - r) / 26, this.length);
- var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
- var maskedWords = extended;
-
- h -= s;
- h = Math.max(0, h);
+ function updateAnimationRunners(animation, newRunner) {
+ if (animation.from && animation.to) {
+ update(animation.from.element);
+ update(animation.to.element);
+ } else {
+ update(animation.element);
+ }
- // Extended mode, copy masked part
- if (maskedWords) {
- for (var i = 0; i < s; i++) {
- maskedWords.words[i] = this.words[i];
+ function update(element) {
+ var runner = getRunner(element);
+ if (runner) runner.setHost(newRunner);
+ }
}
- maskedWords.length = s;
- }
- if (s === 0) {
- // No-op, we should not move anything at all
- } else if (this.length > s) {
- this.length -= s;
- for (i = 0; i < this.length; i++) {
- this.words[i] = this.words[i + s];
+ function handleDestroyedElement() {
+ var runner = getRunner(element);
+ if (runner && (event !== 'leave' || !options.$$domOperationFired)) {
+ runner.end();
+ }
}
- } else {
- this.words[0] = 0;
- this.length = 1;
- }
-
- var carry = 0;
- for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
- var word = this.words[i] | 0;
- this.words[i] = (carry << (26 - r)) | (word >>> r);
- carry = word & mask;
- }
-
- // Push carried bits as a mask
- if (maskedWords && carry !== 0) {
- maskedWords.words[maskedWords.length++] = carry;
- }
-
- if (this.length === 0) {
- this.words[0] = 0;
- this.length = 1;
- }
-
- return this.strip();
- };
-
- BN.prototype.ishrn = function ishrn (bits, hint, extended) {
- // TODO(indutny): implement me
- assert(this.negative === 0);
- return this.iushrn(bits, hint, extended);
- };
- // Shift-left
- BN.prototype.shln = function shln (bits) {
- return this.clone().ishln(bits);
- };
+ function close(rejected) {
+ element.off('$destroy', handleDestroyedElement);
+ removeRunner(element);
- BN.prototype.ushln = function ushln (bits) {
- return this.clone().iushln(bits);
- };
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ options.domOperation();
- // Shift-right
- BN.prototype.shrn = function shrn (bits) {
- return this.clone().ishrn(bits);
- };
+ if (tempClasses) {
+ $$jqLite.removeClass(element, tempClasses);
+ }
- BN.prototype.ushrn = function ushrn (bits) {
- return this.clone().iushrn(bits);
- };
+ runner.complete(!rejected);
+ }
+ };
+ }];
+}];
- // Test if n bit is set
- BN.prototype.testn = function testn (bit) {
- assert(typeof bit === 'number' && bit >= 0);
- var r = bit % 26;
- var s = (bit - r) / 26;
- var q = 1 << r;
-
- // Fast case: bit is much higher than all existing words
- if (this.length <= s) return false;
-
- // Check bit and return
- var w = this.words[s];
-
- return !!(w & q);
- };
-
- // Return only lowers bits of number (in-place)
- BN.prototype.imaskn = function imaskn (bits) {
- assert(typeof bits === 'number' && bits >= 0);
- var r = bits % 26;
- var s = (bits - r) / 26;
-
- assert(this.negative === 0, 'imaskn works only with positive numbers');
-
- if (this.length <= s) {
- return this;
- }
-
- if (r !== 0) {
- s++;
- }
- this.length = Math.min(s, this.length);
-
- if (r !== 0) {
- var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
- this.words[this.length - 1] &= mask;
+/**
+ * @ngdoc directive
+ * @name ngAnimateSwap
+ * @restrict A
+ * @scope
+ *
+ * @description
+ *
+ * ngAnimateSwap is a animation-oriented directive that allows for the container to
+ * be removed and entered in whenever the associated expression changes. A
+ * common usecase for this directive is a rotating banner or slider component which
+ * contains one image being present at a time. When the active image changes
+ * then the old image will perform a `leave` animation and the new element
+ * will be inserted via an `enter` animation.
+ *
+ * @animations
+ * | Animation | Occurs |
+ * |----------------------------------|--------------------------------------|
+ * | {@link ng.$animate#enter enter} | when the new element is inserted to the DOM |
+ * | {@link ng.$animate#leave leave} | when the old element is removed from the DOM |
+ *
+ * @example
+ *
+ *
+ *
+ *
+ * {{ number }}
+ *
+ *
+ *
+ *
+ * angular.module('ngAnimateSwapExample', ['ngAnimate'])
+ * .controller('AppCtrl', ['$scope', '$interval', function($scope, $interval) {
+ * $scope.number = 0;
+ * $interval(function() {
+ * $scope.number++;
+ * }, 1000);
+ *
+ * var colors = ['red','blue','green','yellow','orange'];
+ * $scope.colorClass = function(number) {
+ * return colors[number % colors.length];
+ * };
+ * }]);
+ *
+ *
+ * .container {
+ * height:250px;
+ * width:250px;
+ * position:relative;
+ * overflow:hidden;
+ * border:2px solid black;
+ * }
+ * .container .cell {
+ * font-size:150px;
+ * text-align:center;
+ * line-height:250px;
+ * position:absolute;
+ * top:0;
+ * left:0;
+ * right:0;
+ * border-bottom:2px solid black;
+ * }
+ * .swap-animation.ng-enter, .swap-animation.ng-leave {
+ * transition:0.5s linear all;
+ * }
+ * .swap-animation.ng-enter {
+ * top:-250px;
+ * }
+ * .swap-animation.ng-enter-active {
+ * top:0px;
+ * }
+ * .swap-animation.ng-leave {
+ * top:0px;
+ * }
+ * .swap-animation.ng-leave-active {
+ * top:250px;
+ * }
+ * .red { background:red; }
+ * .green { background:green; }
+ * .blue { background:blue; }
+ * .yellow { background:yellow; }
+ * .orange { background:orange; }
+ *
+ *
+ */
+var ngAnimateSwapDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ transclude: 'element',
+ terminal: true,
+ priority: 600, // we use 600 here to ensure that the directive is caught before others
+ link: function(scope, $element, attrs, ctrl, $transclude) {
+ var previousElement, previousScope;
+ scope.$watchCollection(attrs.ngAnimateSwap || attrs['for'], function(value) {
+ if (previousElement) {
+ $animate.leave(previousElement);
+ }
+ if (previousScope) {
+ previousScope.$destroy();
+ previousScope = null;
+ }
+ if (value || value === 0) {
+ $transclude(function(clone, childScope) {
+ previousElement = clone;
+ previousScope = childScope;
+ $animate.enter(clone, null, $element);
+ });
+ }
+ });
}
-
- return this.strip();
- };
-
- // Return only lowers bits of number
- BN.prototype.maskn = function maskn (bits) {
- return this.clone().imaskn(bits);
};
+}];
- // Add plain number `num` to `this`
- BN.prototype.iaddn = function iaddn (num) {
- assert(typeof num === 'number');
- assert(num < 0x4000000);
- if (num < 0) return this.isubn(-num);
+/**
+ * @ngdoc module
+ * @name ngAnimate
+ * @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 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
+ * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For
+ * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within
+ * the HTML element that the animation will be triggered on.
+ *
+ * ## Directive Support
+ * The following directives are "animation aware":
+ *
+ * | 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 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`:
+ *
+ * ```html
+ *
+ * Fade me in out
+ *
+ *
+ *
+ * ```
+ *
+ * Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
+ *
+ * ```css
+ * /* The starting CSS styles for the enter animation */
+ * .fade.ng-enter {
+ * transition:0.5s linear all;
+ * opacity:0;
+ * }
+ *
+ * /* The finishing CSS styles for the enter animation */
+ * .fade.ng-enter.ng-enter-active {
+ * opacity:1;
+ * }
+ * ```
+ *
+ * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two
+ * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition
+ * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards.
+ *
+ * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions:
+ *
+ * ```css
+ * /* now the element will fade out before it is removed from the DOM */
+ * .fade.ng-leave {
+ * transition:0.5s linear all;
+ * opacity:1;
+ * }
+ * .fade.ng-leave.ng-leave-active {
+ * opacity:0;
+ * }
+ * ```
+ *
+ * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class:
+ *
+ * ```css
+ * /* there is no need to define anything inside of the destination
+ * CSS class since the keyframe will take charge of the animation */
+ * .fade.ng-leave {
+ * animation: my_fade_animation 0.5s linear;
+ * -webkit-animation: my_fade_animation 0.5s linear;
+ * }
+ *
+ * @keyframes my_fade_animation {
+ * from { opacity:1; }
+ * to { opacity:0; }
+ * }
+ *
+ * @-webkit-keyframes my_fade_animation {
+ * from { opacity:1; }
+ * to { opacity:0; }
+ * }
+ * ```
+ *
+ * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element.
+ *
+ * ### CSS Class-based Animations
+ *
+ * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different
+ * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added
+ * and removed.
+ *
+ * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class:
+ *
+ * ```html
+ *
+ * Show and hide me
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since
+ * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest.
+ *
+ * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation
+ * with CSS styles.
+ *
+ * ```html
+ *
+ * Highlight this box
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * We can also make use of CSS keyframes by placing them within the CSS classes.
+ *
+ *
+ * ### CSS Staggering Animations
+ * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
+ * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
+ * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
+ * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
+ * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
+ *
+ * ```css
+ * .my-animation.ng-enter {
+ * /* standard transition code */
+ * transition: 1s linear all;
+ * opacity:0;
+ * }
+ * .my-animation.ng-enter-stagger {
+ * /* this will have a 100ms delay between each successive leave animation */
+ * transition-delay: 0.1s;
+ *
+ * /* As of 1.4.4, this must always be set: it signals ngAnimate
+ * to not accidentally inherit a delay property from another CSS class */
+ * transition-duration: 0s;
+ *
+ * /* if you are using animations instead of transitions you should configure as follows:
+ * animation-delay: 0.1s;
+ * animation-duration: 0s; */
+ * }
+ * .my-animation.ng-enter.ng-enter-active {
+ * /* standard transition styles */
+ * opacity:1;
+ * }
+ * ```
+ *
+ * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
+ * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
+ * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
+ * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired.
+ *
+ * The following code will issue the **ng-leave-stagger** event on the element provided:
+ *
+ * ```js
+ * var kids = parent.children();
+ *
+ * $animate.leave(kids[0]); //stagger index=0
+ * $animate.leave(kids[1]); //stagger index=1
+ * $animate.leave(kids[2]); //stagger index=2
+ * $animate.leave(kids[3]); //stagger index=3
+ * $animate.leave(kids[4]); //stagger index=4
+ *
+ * window.requestAnimationFrame(function() {
+ * //stagger has reset itself
+ * $animate.leave(kids[5]); //stagger index=0
+ * $animate.leave(kids[6]); //stagger index=1
+ *
+ * $scope.$digest();
+ * });
+ * ```
+ *
+ * Stagger animations are currently only supported within CSS-defined animations.
+ *
+ * ### The `ng-animate` CSS class
+ *
+ * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation.
+ * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations).
+ *
+ * Therefore, animations can be applied to an element using this temporary class directly via CSS.
+ *
+ * ```css
+ * .zipper.ng-animate {
+ * transition:0.5s linear all;
+ * }
+ * .zipper.ng-enter {
+ * opacity:0;
+ * }
+ * .zipper.ng-enter.ng-enter-active {
+ * opacity:1;
+ * }
+ * .zipper.ng-leave {
+ * opacity:1;
+ * }
+ * .zipper.ng-leave.ng-leave-active {
+ * opacity:0;
+ * }
+ * ```
+ *
+ * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove
+ * the CSS class once an animation has completed.)
+ *
+ *
+ * ### The `ng-[event]-prepare` class
+ *
+ * This is a special class that can be used to prevent unwanted flickering / flash of content before
+ * the actual animation starts. The class is added as soon as an animation is initialized, but removed
+ * before the actual animation starts (after waiting for a $digest).
+ * It is also only added for *structural* animations (`enter`, `move`, and `leave`).
+ *
+ * In practice, flickering can appear when nesting elements with structural animations such as `ngIf`
+ * into elements that have class-based animations such as `ngClass`.
+ *
+ * ```html
+ *
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * It is possible that during the `enter` animation, the `.message` div will be briefly visible before it starts animating.
+ * In that case, you can add styles to the CSS that make sure the element stays hidden before the animation starts:
+ *
+ * ```css
+ * .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
+ * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
+ * `module.animation()` module function we can register the animation.
+ *
+ * Let's see an example of a enter/leave animation using `ngRepeat`:
+ *
+ * ```html
+ *
+ * {{ item }}
+ *
+ * ```
+ *
+ * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`:
+ *
+ * ```js
+ * myModule.animation('.slide', [function() {
+ * return {
+ * // make note that other events (like addClass/removeClass)
+ * // have different function input parameters
+ * enter: function(element, doneFn) {
+ * jQuery(element).fadeIn(1000, doneFn);
+ *
+ * // remember to call doneFn so that AngularJS
+ * // knows that the animation has concluded
+ * },
+ *
+ * move: function(element, doneFn) {
+ * jQuery(element).fadeIn(1000, doneFn);
+ * },
+ *
+ * leave: function(element, doneFn) {
+ * jQuery(element).fadeOut(1000, doneFn);
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
+ * greensock.js and velocity.js.
+ *
+ * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define
+ * our animations inside of the same registered animation, however, the function input arguments are a bit different:
+ *
+ * ```html
+ *
+ * this box is moody
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * ```js
+ * myModule.animation('.colorful', [function() {
+ * return {
+ * addClass: function(element, className, doneFn) {
+ * // do some cool animation and call the doneFn
+ * },
+ * removeClass: function(element, className, doneFn) {
+ * // do some cool animation and call the doneFn
+ * },
+ * setClass: function(element, addedClass, removedClass, doneFn) {
+ * // do some cool animation and call the doneFn
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ## 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 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**:
+ *
+ * ```html
+ *
+ * Slide in and out
+ *
+ * ```
+ *
+ * ```js
+ * myModule.animation('.slide', [function() {
+ * return {
+ * enter: function(element, doneFn) {
+ * jQuery(element).slideIn(1000, doneFn);
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ```css
+ * .slide.ng-enter {
+ * transition:0.5s linear all;
+ * transform:translateY(-100px);
+ * }
+ * .slide.ng-enter.ng-enter-active {
+ * transform:translateY(0);
+ * }
+ * ```
+ *
+ * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the
+ * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from
+ * our own JS-based animation code:
+ *
+ * ```js
+ * myModule.animation('.slide', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element) {
+* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
+ * return $animateCss(element, {
+ * event: 'enter',
+ * structural: true
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
+ *
+ * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or
+ * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that
+ * data into `$animateCss` directly:
+ *
+ * ```js
+ * myModule.animation('.slide', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element) {
+ * return $animateCss(element, {
+ * event: 'enter',
+ * structural: true,
+ * addClass: 'maroon-setting',
+ * from: { height:0 },
+ * to: { height: 200 }
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * Now we can fill in the rest via our transition CSS code:
+ *
+ * ```css
+ * /* the transition tells ngAnimate to make the animation happen */
+ * .slide.ng-enter { transition:0.5s linear all; }
+ *
+ * /* this extra CSS class will be absorbed into the transition
+ * since the $animateCss code is adding the class */
+ * .maroon-setting { background:red; }
+ * ```
+ *
+ * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over.
+ *
+ * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
+ *
+ * ## Animation Anchoring (via `ng-animate-ref`)
+ *
+ * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
+ * structural areas of an application (like views) by pairing up elements using an attribute
+ * called `ng-animate-ref`.
+ *
+ * Let's say for example we have two views that are managed by `ng-view` and we want to show
+ * that there is a relationship between two components situated in within these views. By using the
+ * `ng-animate-ref` attribute we can identify that the two components are paired together and we
+ * can then attach an animation, which is triggered when the view changes.
+ *
+ * Say for example we have the following template code:
+ *
+ * ```html
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * Now, when the view changes (once the link is clicked), ngAnimate will examine the
+ * HTML contents to see if there is a match reference between any components in the view
+ * that is leaving and the view that is entering. It will scan both the view which is being
+ * removed (leave) and inserted (enter) to see if there are any paired DOM elements that
+ * contain a matching ref value.
+ *
+ * The two images match since they share the same ref value. ngAnimate will now create a
+ * transport element (which is a clone of the first image element) and it will then attempt
+ * to animate to the position of the second image element in the next view. For the animation to
+ * work a special CSS class called `ng-anchor` will be added to the transported element.
+ *
+ * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then
+ * ngAnimate will handle the entire transition for us as well as the addition and removal of
+ * any changes of CSS classes between the elements:
+ *
+ * ```css
+ * .banner.ng-anchor {
+ * /* this animation will last for 1 second since there are
+ * two phases to the animation (an `in` and an `out` phase) */
+ * transition:0.5s linear all;
+ * }
+ * ```
+ *
+ * We also **must** include animations for the views that are being entered and removed
+ * (otherwise anchoring wouldn't be possible since the new view would be inserted right away).
+ *
+ * ```css
+ * .view-animation.ng-enter, .view-animation.ng-leave {
+ * transition:0.5s linear all;
+ * position:fixed;
+ * left:0;
+ * top:0;
+ * width:100%;
+ * }
+ * .view-animation.ng-enter {
+ * transform:translateX(100%);
+ * }
+ * .view-animation.ng-leave,
+ * .view-animation.ng-enter.ng-enter-active {
+ * transform:translateX(0%);
+ * }
+ * .view-animation.ng-leave.ng-leave-active {
+ * transform:translateX(-100%);
+ * }
+ * ```
+ *
+ * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur:
+ * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away
+ * from its origin. Once that animation is over then the `in` stage occurs which animates the
+ * element to its destination. The reason why there are two animations is to give enough time
+ * for the enter animation on the new element to be ready.
+ *
+ * The example above sets up a transition for both the in and out phases, but we can also target the out or
+ * in phases directly via `ng-anchor-out` and `ng-anchor-in`.
+ *
+ * ```css
+ * .banner.ng-anchor-out {
+ * transition: 0.5s linear all;
+ *
+ * /* the scale will be applied during the out animation,
+ * but will be animated away when the in animation runs */
+ * transform: scale(1.2);
+ * }
+ *
+ * .banner.ng-anchor-in {
+ * transition: 1s linear all;
+ * }
+ * ```
+ *
+ *
+ *
+ *
+ * ### Anchoring Demo
+ *
+
+
+ Home
+
+
+
+
+ .record {
+ display:block;
+ font-size:20px;
}
-
- this.negative = 0;
- this.isubn(num);
- this.negative = 1;
- return this;
- }
-
- // Add without checks
- return this._iaddn(num);
- };
-
- BN.prototype._iaddn = function _iaddn (num) {
- this.words[0] += num;
-
- // Carry
- for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
- this.words[i] -= 0x4000000;
- if (i === this.length - 1) {
- this.words[i + 1] = 1;
- } else {
- this.words[i + 1]++;
+ .profile {
+ background:black;
+ color:white;
+ font-size:100px;
}
- }
- this.length = Math.max(this.length, i + 1);
-
- return this;
- };
+ .view-container {
+ position:relative;
+ }
+ .view-container > .view.ng-animate {
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ min-height:500px;
+ }
+ .view.ng-enter, .view.ng-leave,
+ .record.ng-anchor {
+ transition:0.5s linear all;
+ }
+ .view.ng-enter {
+ transform:translateX(100%);
+ }
+ .view.ng-enter.ng-enter-active, .view.ng-leave {
+ transform:translateX(0%);
+ }
+ .view.ng-leave.ng-leave-active {
+ transform:translateX(-100%);
+ }
+ .record.ng-anchor-out {
+ background:red;
+ }
+
+
+ *
+ * ### How is the element transported?
+ *
+ * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
+ * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
+ * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
+ * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
+ * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
+ * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
+ * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
+ * will become visible since the shim class will be removed.
+ *
+ * ### How is the morphing handled?
+ *
+ * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
+ * what CSS classes differ between the starting element and the destination element. These different CSS classes
+ * will be added/removed on the anchor element and a transition will be applied (the transition that is provided
+ * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
+ * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
+ * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
+ * the cloned element is placed inside of root element which is likely close to the body element).
+ *
+ * Note that if the root element is on the `` element then the cloned node will be placed inside of body.
+ *
+ *
+ * ## Using $animate in your directive code
+ *
+ * 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
+ *
+ * ```html
+ * Hi there
+ * ```
+ *
+ * ```js
+ * ngModule.directive('greetingBox', ['$animate', function($animate) {
+ * return function(scope, element, attrs) {
+ * attrs.$observe('active', function(value) {
+ * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
+ * });
+ * });
+ * }]);
+ * ```
+ *
+ * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element
+ * in our HTML code then we can trigger a CSS or JS animation to happen.
+ *
+ * ```css
+ * /* normally we would create a CSS class to reference on the element */
+ * greeting-box.on { transition:0.5s linear all; background:green; color:white; }
+ * ```
+ *
+ * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's
+ * possible be sure to visit the {@link ng.$animate $animate service API page}.
+ *
+ *
+ * ## Callbacks and Promises
+ *
+ * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger
+ * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has
+ * ended by chaining onto the returned promise that animation method returns.
+ *
+ * ```js
+ * // somewhere within the depths of the directive
+ * $animate.enter(element, parent).then(function() {
+ * //the animation has completed
+ * });
+ * ```
+ *
+ * (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
+ * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view
+ * routing controller to hook into that:
+ *
+ * ```js
+ * ngModule.controller('HomePageController', ['$animate', function($animate) {
+ * $animate.on('enter', ngViewElement, function(element) {
+ * // the animation for this route has completed
+ * }]);
+ * }])
+ * ```
+ *
+ * (Note that you will need to trigger a digest within the callback to get AngularJS to notice any scope-related changes.)
+ */
- // Subtract plain number `num` from `this`
- BN.prototype.isubn = function isubn (num) {
- assert(typeof num === 'number');
- assert(num < 0x4000000);
- if (num < 0) return this.iaddn(-num);
+var copy;
+var extend;
+var forEach;
+var isArray;
+var isDefined;
+var isElement;
+var isFunction;
+var isObject;
+var isString;
+var isUndefined;
+var jqLite;
+var noop;
- if (this.negative !== 0) {
- this.negative = 0;
- this.iaddn(num);
- this.negative = 1;
- return this;
- }
+/**
+ * @ngdoc service
+ * @name $animate
+ * @kind object
+ *
+ * @description
+ * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
+ *
+ * Click here {@link ng.$animate to learn more about animations with `$animate`}.
+ */
+angular.module('ngAnimate', [], function initAngularHelpers() {
+ // Access helpers from AngularJS core.
+ // Do it inside a `config` block to ensure `window.angular` is available.
+ noop = angular.noop;
+ copy = angular.copy;
+ extend = angular.extend;
+ jqLite = angular.element;
+ forEach = angular.forEach;
+ isArray = angular.isArray;
+ isString = angular.isString;
+ isObject = angular.isObject;
+ isUndefined = angular.isUndefined;
+ isDefined = angular.isDefined;
+ isFunction = angular.isFunction;
+ isElement = angular.isElement;
+})
+ .info({ angularVersion: '1.7.5' })
+ .directive('ngAnimateSwap', ngAnimateSwapDirective)
- this.words[0] -= num;
+ .directive('ngAnimateChildren', $$AnimateChildrenDirective)
+ .factory('$$rAFScheduler', $$rAFSchedulerFactory)
- if (this.length === 1 && this.words[0] < 0) {
- this.words[0] = -this.words[0];
- this.negative = 1;
- } else {
- // Carry
- for (var i = 0; i < this.length && this.words[i] < 0; i++) {
- this.words[i] += 0x4000000;
- this.words[i + 1] -= 1;
- }
- }
+ .provider('$$animateQueue', $$AnimateQueueProvider)
+ .provider('$$animateCache', $$AnimateCacheProvider)
+ .provider('$$animation', $$AnimationProvider)
- return this.strip();
- };
+ .provider('$animateCss', $AnimateCssProvider)
+ .provider('$$animateCssDriver', $$AnimateCssDriverProvider)
- BN.prototype.addn = function addn (num) {
- return this.clone().iaddn(num);
- };
+ .provider('$$animateJs', $$AnimateJsProvider)
+ .provider('$$animateJsDriver', $$AnimateJsDriverProvider);
- BN.prototype.subn = function subn (num) {
- return this.clone().isubn(num);
- };
- BN.prototype.iabs = function iabs () {
- this.negative = 0;
+})(window, window.angular);
- return this;
- };
+},{}],175:[function(require,module,exports){
+require('./angular-animate');
+module.exports = 'ngAnimate';
- BN.prototype.abs = function abs () {
- return this.clone().iabs();
- };
+},{"./angular-animate":174}],176:[function(require,module,exports){
+/**
+ * @license AngularJS v1.7.5
+ * (c) 2010-2018 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular) {'use strict';
- BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
- var len = num.length + shift;
- var i;
-
- this._expand(len);
-
- var w;
- var carry = 0;
- for (i = 0; i < num.length; i++) {
- w = (this.words[i + shift] | 0) + carry;
- var right = (num.words[i] | 0) * mul;
- w -= right & 0x3ffffff;
- carry = (w >> 26) - ((right / 0x4000000) | 0);
- this.words[i + shift] = w & 0x3ffffff;
- }
- for (; i < this.length - shift; i++) {
- w = (this.words[i + shift] | 0) + carry;
- carry = w >> 26;
- this.words[i + shift] = w & 0x3ffffff;
- }
-
- if (carry === 0) return this.strip();
-
- // Subtraction overflow
- assert(carry === -1);
- carry = 0;
- for (i = 0; i < this.length; i++) {
- w = -(this.words[i] | 0) + carry;
- carry = w >> 26;
- this.words[i] = w & 0x3ffffff;
- }
- this.negative = 1;
-
- return this.strip();
- };
-
- BN.prototype._wordDiv = function _wordDiv (num, mode) {
- var shift = this.length - num.length;
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- var a = this.clone();
- var b = num;
+var $sanitizeMinErr = angular.$$minErr('$sanitize');
+var bind;
+var extend;
+var forEach;
+var isArray;
+var isDefined;
+var lowercase;
+var noop;
+var nodeContains;
+var htmlParser;
+var htmlSanitizeWriter;
- // Normalize
- var bhi = b.words[b.length - 1] | 0;
- var bhiBits = this._countBits(bhi);
- shift = 26 - bhiBits;
- if (shift !== 0) {
- b = b.ushln(shift);
- a.iushln(shift);
- bhi = b.words[b.length - 1] | 0;
- }
+/**
+ * @ngdoc module
+ * @name ngSanitize
+ * @description
+ *
+ * The `ngSanitize` module provides functionality to sanitize HTML.
+ *
+ * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
+ */
- // Initialize quotient
- var m = a.length - b.length;
- var q;
+/**
+ * @ngdoc service
+ * @name $sanitize
+ * @kind function
+ *
+ * @description
+ * 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 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 $compileProvider}.
+ *
+ * The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
+ *
+ * @param {string} html HTML input.
+ * @returns {string} Sanitized HTML.
+ *
+ * @example
+
+
+
+
+ Snippet:
+
+
+
Directive
+
How
+
Source
+
Rendered
+
+
+
ng-bind-html
+
Automatically uses $sanitize
+
<div ng-bind-html="snippet"> </div>
+
+
+
+
ng-bind-html
+
Bypass $sanitize by explicitly trusting the dangerous value
+
+
+ it('should sanitize the html snippet by default', function() {
+ expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
+ toBe('
an html\nclick here\nsnippet
');
+ });
- if (mode !== 'mod') {
- q = new BN(null);
- q.length = m + 1;
- q.words = new Array(q.length);
- for (var i = 0; i < q.length; i++) {
- q.words[i] = 0;
- }
- }
+ it('should inline raw snippet if bound to a trusted value', function() {
+ expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).
+ toBe("
an html\n" +
+ "click here\n" +
+ "snippet
");
+ });
- var diff = a.clone()._ishlnsubmul(b, 1, m);
- if (diff.negative === 0) {
- a = diff;
- if (q) {
- q.words[m] = 1;
- }
- }
+ it('should escape snippet without any filter', function() {
+ expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).
+ toBe("<p style=\"color:blue\">an html\n" +
+ "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
+ "snippet</p>");
+ });
- for (var j = m - 1; j >= 0; j--) {
- var qj = (a.words[b.length + j] | 0) * 0x4000000 +
- (a.words[b.length + j - 1] | 0);
+ it('should update', function() {
+ element(by.model('snippet')).clear();
+ element(by.model('snippet')).sendKeys('new text');
+ expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
+ toBe('new text');
+ expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).toBe(
+ 'new text');
+ expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).toBe(
+ "new <b onclick=\"alert(1)\">text</b>");
+ });
+
+
+ */
- // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
- // (0x7ffffff)
- qj = Math.min((qj / bhi) | 0, 0x3ffffff);
- a._ishlnsubmul(b, qj, j);
- while (a.negative !== 0) {
- qj--;
- a.negative = 0;
- a._ishlnsubmul(b, 1, j);
- if (!a.isZero()) {
- a.negative ^= 1;
- }
- }
- if (q) {
- q.words[j] = qj;
- }
- }
- if (q) {
- q.strip();
- }
- a.strip();
+/**
+ * @ngdoc provider
+ * @name $sanitizeProvider
+ * @this
+ *
+ * @description
+ * Creates and configures {@link $sanitize} instance.
+ */
+function $SanitizeProvider() {
+ var hasBeenInstantiated = false;
+ var svgEnabled = false;
- // Denormalize
- if (mode !== 'div' && shift !== 0) {
- a.iushrn(shift);
+ this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
+ hasBeenInstantiated = true;
+ if (svgEnabled) {
+ extend(validElements, svgElements);
}
-
- return {
- div: q || null,
- mod: a
+ return function(html) {
+ var buf = [];
+ htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
+ return !/^unsafe:/.test($$sanitizeUri(uri, isImage));
+ }));
+ return buf.join('');
};
- };
+ }];
- // NOTE: 1) `mode` can be set to `mod` to request mod only,
- // to `div` to request div only, or be absent to
- // request both div & mod
- // 2) `positive` is true if unsigned mod is requested
- BN.prototype.divmod = function divmod (num, mode, positive) {
- assert(!num.isZero());
- if (this.isZero()) {
- return {
- div: new BN(0),
- mod: new BN(0)
- };
+ /**
+ * @ngdoc method
+ * @name $sanitizeProvider#enableSvg
+ * @kind function
+ *
+ * @description
+ * Enables a subset of svg to be supported by the sanitizer.
+ *
+ *
+ *
By enabling this setting without taking other precautions, you might expose your
+ * application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned
+ * outside of the containing element and be rendered over other elements on the page (e.g. a login
+ * link). Such behavior can then result in phishing incidents.
+ *
+ *
To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg
+ * tags within the sanitized content:
+ *
+ * @param {boolean=} flag Enable or disable SVG support in the sanitizer.
+ * @returns {boolean|$sanitizeProvider} Returns the currently configured value if called
+ * without an argument or self for chaining otherwise.
+ */
+ this.enableSvg = function(enableSvg) {
+ if (isDefined(enableSvg)) {
+ svgEnabled = enableSvg;
+ return this;
+ } else {
+ return svgEnabled;
}
+ };
- var div, mod, res;
- if (this.negative !== 0 && num.negative === 0) {
- res = this.neg().divmod(num, mode);
-
- if (mode !== 'mod') {
- div = res.div.neg();
- }
- if (mode !== 'div') {
- mod = res.mod.neg();
- if (positive && mod.negative !== 0) {
- mod.iadd(num);
- }
+ /**
+ * @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};
}
- return {
- div: div,
- mod: mod
- };
+ addElementsTo(svgElements, elements.svgElements);
+ addElementsTo(voidElements, elements.htmlVoidElements);
+ addElementsTo(validElements, elements.htmlVoidElements);
+ addElementsTo(validElements, elements.htmlElements);
}
- if (this.negative === 0 && num.negative !== 0) {
- res = this.divmod(num.neg(), mode);
+ return this;
+ };
- if (mode !== 'mod') {
- div = res.div.neg();
- }
- return {
- div: div,
- mod: res.mod
- };
+ /**
+ * @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;
+ };
- if ((this.negative & num.negative) !== 0) {
- res = this.neg().divmod(num.neg(), mode);
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // Private stuff
+ //////////////////////////////////////////////////////////////////////////////////////////////////
- if (mode !== 'div') {
- mod = res.mod.neg();
- if (positive && mod.negative !== 0) {
- mod.isub(num);
- }
- }
+ bind = angular.bind;
+ extend = angular.extend;
+ forEach = angular.forEach;
+ isArray = angular.isArray;
+ isDefined = angular.isDefined;
+ lowercase = angular.$$lowercase;
+ noop = angular.noop;
- return {
- div: res.div,
- mod: mod
- };
- }
+ htmlParser = htmlParserImpl;
+ htmlSanitizeWriter = htmlSanitizeWriterImpl;
- // Both numbers are positive at this point
+ nodeContains = window.Node.prototype.contains || /** @this */ function(arg) {
+ // eslint-disable-next-line no-bitwise
+ return !!(this.compareDocumentPosition(arg) & 16);
+ };
- // Strip both numbers to approximate shift value
- if (num.length > this.length || this.cmp(num) < 0) {
- return {
- div: new BN(0),
- mod: this
- };
- }
+ // Regular Expressions for parsing tags and attributes
+ var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ // Match everything outside of normal chars and " (quote character)
+ NON_ALPHANUMERIC_REGEXP = /([^#-~ |!])/g;
- // Very short reduction
- if (num.length === 1) {
- if (mode === 'div') {
- return {
- div: this.divn(num.words[0]),
- mod: null
- };
- }
- if (mode === 'mod') {
- return {
- div: null,
- mod: new BN(this.modn(num.words[0]))
- };
- }
+ // Good source of info about elements and attributes
+ // http://dev.w3.org/html5/spec/Overview.html#semantics
+ // http://simon.html5.org/html-elements
- return {
- div: this.divn(num.words[0]),
- mod: new BN(this.modn(num.words[0]))
- };
- }
+ // Safe Void Elements - HTML5
+ // http://dev.w3.org/html5/spec/Overview.html#void-elements
+ var voidElements = stringToMap('area,br,col,hr,img,wbr');
- return this._wordDiv(num, mode);
- };
+ // Elements that you can, intentionally, leave open (and which close themselves)
+ // http://dev.w3.org/html5/spec/Overview.html#optional-tags
+ var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),
+ optionalEndTagInlineElements = stringToMap('rp,rt'),
+ optionalEndTagElements = extend({},
+ optionalEndTagInlineElements,
+ optionalEndTagBlockElements);
- // Find `this` / `num`
- BN.prototype.div = function div (num) {
- return this.divmod(num, 'div', false).div;
- };
+ // Safe Block Elements - HTML5
+ 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'));
- // Find `this` % `num`
- BN.prototype.mod = function mod (num) {
- return this.divmod(num, 'mod', false).mod;
- };
+ // Inline Elements - HTML5
+ 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'));
- BN.prototype.umod = function umod (num) {
- return this.divmod(num, 'mod', true).mod;
- };
+ // 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 = 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');
- // Find Round(`this` / `num`)
- BN.prototype.divRound = function divRound (num) {
- var dm = this.divmod(num);
+ // Blocked Elements (will be stripped)
+ var blockedElements = stringToMap('script,style');
- // Fast case - exact division
- if (dm.mod.isZero()) return dm.div;
+ var validElements = extend({},
+ voidElements,
+ blockElements,
+ inlineElements,
+ optionalEndTagElements);
- var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
+ //Attributes that have href and hence need to be sanitized
+ var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base');
- var half = num.ushrn(1);
- var r2 = num.andln(1);
- var cmp = mod.cmp(half);
+ 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');
- // Round down
- if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
+ // SVG attributes (without "id" and "name" attributes)
+ // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
+ 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);
- // Round up
- return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
- };
+ var validAttrs = extend({},
+ uriAttrs,
+ svgAttrs,
+ htmlAttrs);
- BN.prototype.modn = function modn (num) {
- assert(num <= 0x3ffffff);
- var p = (1 << 26) % num;
+ function stringToMap(str, lowercaseKeys) {
+ return arrayToMap(str.split(','), lowercaseKeys);
+ }
- var acc = 0;
- for (var i = this.length - 1; i >= 0; i--) {
- acc = (p * acc + (this.words[i] | 0)) % num;
+ function arrayToMap(items, lowercaseKeys) {
+ var obj = {}, i;
+ for (i = 0; i < items.length; i++) {
+ obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;
}
+ return obj;
+ }
- return acc;
- };
-
- // In-place division by number
- BN.prototype.idivn = function idivn (num) {
- assert(num <= 0x3ffffff);
-
- var carry = 0;
- for (var i = this.length - 1; i >= 0; i--) {
- var w = (this.words[i] | 0) + carry * 0x4000000;
- this.words[i] = (w / num) | 0;
- carry = w % num;
+ function addElementsTo(elementsMap, newElements) {
+ if (newElements && newElements.length) {
+ extend(elementsMap, arrayToMap(newElements));
}
+ }
- return this.strip();
- };
-
- BN.prototype.divn = function divn (num) {
- return this.clone().idivn(num);
- };
-
- BN.prototype.egcd = function egcd (p) {
- assert(p.negative === 0);
- assert(!p.isZero());
-
- var x = this;
- var y = p.clone();
-
- if (x.negative !== 0) {
- x = x.umod(p);
+ /**
+ * 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.
+ * Support: Safari 10.x -> XHR strategy
+ * Support: Firefox -> DomParser strategy
+ */
+ var getInertBodyElement /* function(html: string): HTMLBodyElement */ = (function(window, document) {
+ var inertDocument;
+ if (document && document.implementation) {
+ inertDocument = document.implementation.createHTMLDocument('inert');
} else {
- x = x.clone();
- }
-
- // A * x + B * y = x
- var A = new BN(1);
- var B = new BN(0);
-
- // C * x + D * y = y
- var C = new BN(0);
- var D = new BN(1);
-
- var g = 0;
-
- while (x.isEven() && y.isEven()) {
- x.iushrn(1);
- y.iushrn(1);
- ++g;
+ throw $sanitizeMinErr('noinert', 'Can\'t create an inert html document');
}
+ var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');
- var yp = y.clone();
- var xp = x.clone();
-
- while (!x.isZero()) {
- for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
- if (i > 0) {
- x.iushrn(i);
- while (i-- > 0) {
- if (A.isOdd() || B.isOdd()) {
- A.iadd(yp);
- B.isub(xp);
- }
-
- A.iushrn(1);
- B.iushrn(1);
- }
+ // Check for the Safari 10.1 bug - which allows JS to run inside the SVG G element
+ inertBodyElement.innerHTML = '';
+ if (!inertBodyElement.querySelector('svg')) {
+ return getInertBodyElement_XHR;
+ } else {
+ // Check for the Firefox bug - which prevents the inner img JS from being sanitized
+ inertBodyElement.innerHTML = '