
define('ccFilters',[], function () {
    return {
        "v": 3,
        "loc": null,
        "iam": {
            "gc": {
                "regex": "Personal",
                "tag": "General Consumer"
            },
            "bo": {
                "uri": "business",
                "tag": "Business",
                "regex": "Business"
            },
            "cs": {
                "uri": "student",
                "tag": "Student",
                "regex": "Student"
            }
        },
        "emv": {
            "n": {
                "regex": "All Cards"
            },
            "pn": {
                "uri": "chip-and-pin",
                "tag": "Chip and Pin",
                "regex": "Chip and Pin"
            },
            "sg": {
                "uri": "emv",
                "tag": "Chip, Pin, and Signature",
                "regex": "Chip, Pin, and Signature"
            }
        },
        "mc": {
            "ex": {
                "uri": "excellent-credit",
                "tag": "Excellent Credit",
                "regex": "Excellent"
            },
            "gd": {
                "uri": "good-credit",
                "tag": "Good Credit",
                "regex": "Good"
            },
            "fr": {
                "uri": "fair-credit",
                "tag": "Fair Credit",
                "regex": "Fair"
            },
            "bd": {
                "uri": "bad-credit",
                "tag": "Bad Credit",
                "regex": "Bad"
            },
            "nc": {
                "uri": "no-credit",
                "tag": "No Credit or Limited History",
                "regex": "Limited History",
                "aliasuri": ["student"]
            }
        },
        "iw": {
            "pch": {
                "uri": "0-apr",
                "tag": "0% on Purchases"
            },
            "bt": {
                "uri": "balance-transfer",
                "tag": "0% on Transfers"
            },
            "reg": {
                "uri": "low-interest",
                "tag": "Regular Rate"
            },
            "af": {
                "uri": "no-annual-fee",
                "tag": "No Annual Fee"
            },
            "rw": {
                "uri": "rewards",
                "tag": "Rewards"
            }
        },
        "iws": {
            "sc": {
                "uri": "secured",
                "tag": "Secured Card"
            },
            "us": {
                "uri": "unsecured",
                "tag": "Unsecured Card"
            }
        },
        "rw": {
            "cb": {
                "uri": "cash-back",
                "regex": "Cash"
            },
            "gas": {
                "uri": "gas",
                "regex": "Gas"
            },
            "ho": {
                "uri": "hotel",
                "regex": "Hotel"
            },
            "mi": {
                "uri": "airline-miles",
                "regex": "Miles"
            },
            "pt": {
                "uri": "points",
                "regex": "Points"
            }
        },
        "nw": {
            "am": {
                "uri": "american-express",
                "regex": "American Express"
            },
            "vi": {
                "uri": "visa",
                "regex": "VISA"
            },
            "mc": {
                "uri": "mastercard",
                "regex": "Mastercard"
            },
            "di": {
                "uri": "discover",
                "regex": "Discover"
            }
        },
        "bt": {
            "n": {
                "uri": "no-balance-transfer-fee"
            }
        },
        "ft": {
            "y": {
                "uri": "no-foreign-transaction-fee"
            }
        },
        // "emv": {
        //     "n": [],
        //     "pn": {
        //         "uri": "chip-and-pin",
        //         "aliasuri": ["emv"]
        //     },
        //     "sg": {
        //         "uri": "emv"
        //     }
        // },
        "pic": {
            "y": {
                "uri": "photo"
            },
            "n": []
        },
        "cha": {
            "y": {
                "uri": "charity"
            },
            "n": []
        },
        "stcrd": {
            "y": {
                "uri": "store"
            },
            "n": []
        },
        "chcrd": {
            "y": {
                "uri": "charge-cards"
            },
            "n": []
        },
        "defaults": {
            "iam": "gc",
            "emv": "n",
            "mc": null,
            "loc": null,
            "iw": {
                "pch": false,
                "bt": false,
                "reg": false,
                "af": false,
                "rw": false
            },
            "iws": {
                "sc": true,
                "us": true,
            },
            "rw": {
                "cb": true,
                "gas": true,
                "ho": true,
                "mi": true,
                "pt": true
            },
            "reg": 17,
            "nw": {
                "vi": true,
                "mc": true,
                "am": true,
                "di": true
            },
            "bt": {
                "n": true,
                "bt3": true,
                "bt4": true,
                "bt5": true
            },
            // "emv": {
            //     "n": true,
            //     "pn": true,
            //     "sg": true
            // },
            "pic": "n",
            "cha": "n",
            "ft": "n",
            "inst": [
                {
                    "checked": true,
                    "uid": 13000208,
                    "code": 1,
                    "uri": "american-express",
                    "name": "American Express"
                },
                {
                    "checked": true,
                    "uid": 13000450,
                    "code": 2,
                    "uri": "bank-of-america",
                    "name": "Bank of America"
                },
                {
                    "checked": true,
                    "uid": 13000817,
                    "code": 3,
                    "uri": "barclays",
                    "name": "Barclays",
                },
                {
                    "checked": true,
                    "uid": 13001087,
                    "code": 4,
                    "uri": "capital-one",
                    "name": "Capital One"
                },
                {
                    "checked": true,
                    "uid": 13001251,
                    "code": 5,
                    "uri": "chase",
                    "name": "Chase"
                },
                {
                    "checked": true,
                    "uid": 13001291,
                    "code": 6,
                    "uri": "citibank",
                    "name": "Citibank"
                },
                {
                    "checked": true,
                    "uid": 13001903,
                    "code": 12,
                    "uri": "credit-one",
                    "name": "Credit One Bank"
                },
                {
                    "checked": true,
                    "uid": 13002009,
                    "code": 7,
                    "uri": "discover",
                    "name": "Discover"
                },
                {
                    "checked": true,
                    "uid": 13003011,
                    "code": 8,
                    "uri": "first-national",
                    "name": "First National"
                },
                {
                    "checked": true,
                    "uid": 13003688,
                    "code": 9,
                    "uri": "hsbc",
                    "name": "HSBC"
                },
                {
                    "checked": true,
                    "uid": 13007637,
                    "code": 10,
                    "uri": "us-bank",
                    "name": "US Bank"
                },
                {
                    "checked": true,
                    "uid": 13007950,
                    "code": 11,
                    "uri": "wells-fargo",
                    "name": "Wells Fargo"
                },
                {
                    "checked": true,
                    "uid": 13003061,
                    "code": -1,
                    "uri": "first-premier",
                    "name": "First Premier",
                    "value": "First PREMIER Bank",
                    "invisible": true
                },
                {
                    "checked": true,
                    "uid": 13000082,
                    "code": -1,
                    "uri": "advanta",
                    "name": "Advanta",
                    "value": "Advanta",
                    "invisible": true
                }
            ],
            "inst_o": true,
            "stcrd": "n",
            "chcrd": "n",
            "srt": "ftr"
        }
    };
});

var obfuscate = "cc";

//@ts-check
(function (factory) {
	if (typeof module === "object" && typeof module.exports === "object") {
		//@ts-ignore
		var v = factory(require, exports);
		if (v !== undefined) module.exports = v;
	}
	//@ts-ignore
	else if (typeof define === "function" && define.amd) {
		//@ts-ignore
		define('ith-ccModel',["require", "exports", "angular", "pitLS"], factory);
	}
})(function (require, exports) {
	/** @type {ng.IAngularStatic} */
	var angular = require("angular"),
		Util = require("polyfills");

	// pitLS = require('pitLS');

	/**
	 * Use the line above as the first line of any JS code when you wish to inform the post-commit hook that we need to obfuscate credit card fields in the minified version.
	 * Note that the line above will be removed in the obfuscated version.
	 */

	function none_if_empty(val) {
		if (val) {
			return val;
		} else {
			return "None";
		}
	}
	/**
	 * @constructor
	 * @param {{[key:string]:any}} data
	 */
	function CreditCard(data) {
		var _this = this;
		/** @type {boolean} */
		this.eagle_data_offer = false;
		/** @type {string} */
		this.sectiontype = "";
		for (var i in data) {
			this[i] = data[i];
		}

		// get rewards redemption txt
		_this.Ej = null;

		// variables adjustment depending on the source of the card data
		if ("rew_redeem" in _this) _this.YA = _this.rew_redeem;

		if ("YA" in _this) {
			_this.Ej = _this.YA;
			if ((_this.Sz + "").indexOf("Gas") > -1) {
				_this.Ej += " - Extra on Gas";
			}
		}

		if (!_this.bF) _this.bF = "";
		if ("details_page" in _this) _this.bF = _this.details_page;
		if ("DetailsHtmlPageName" in _this) _this.bF = _this.DetailsHtmlPageName;

		if ("p_reg_apr_max" in _this && "p_reg_apr_min" in _this) _this.sU = [_this.p_reg_apr_min, _this.p_reg_apr_max];

		if ("fk_card_class" in _this) _this.Nb = _this.fk_card_class.join("; ");
		if ("img_name" in _this) _this.gW = _this.img_name;
		if ("ImageURL" in _this) _this.gW = _this.ImageURL;
		if ("img_name_full" in _this) _this.IMAGE_NAME_FULL = _this.img_name_full;

		if ("rating" in _this) _this.rG = _this.rating;
		if ("votes" in _this) _this.vT = _this.votes;

		if ("pdt_type" in _this) _this.BJ = _this.pdt_type;
		if ("SecuredCardType" in _this) _this.BJ = _this.SecuredCardType.toLowerCase();

		if ("min_credit_reqd" in _this) _this.aR = (_this.min_credit_reqd || []).join(", ");
		if ("MinCreditRequired" in _this) _this.aR = _this.MinCreditRequired.toLowerCase();

		if ("minimum_credit_texts" in _this) _this.MIN_CREDIT_TEXTS = (_this.minimum_credit_texts || []).join(", ");

		if ("ots_fee" in _this) _this.bU = _this.ots_fee;
		if ("TotalOneTimeFees" in _this) _this.bU = _this.TotalOneTimeFees;

		if ("annl_fee" in _this) _this.Rb = _this.annl_fee;
		if ("AnnualFee" in _this) _this.Rb = _this.AnnualFee;

		if ("instant_approval" in _this) {
			_this.iA = _this.instant_approval == "Y";
		}

		if ("mnth_fee" in _this) _this.pU = _this.mnth_fee;
		else if ("monthly_fee" in _this) _this.pU = _this.monthly_fee;
		else if ("MonthlyFee" in _this) _this.pU = _this.MonthlyFee;

		if ("rew_earn_rt" in _this) _this.eR = _this.rew_earn_rt;
		if ("EarnRate" in _this) _this.eR = _this.EarnRate;
		if ("rew_earn_rt_linked" in _this) _this.Wz = _this.rew_earn_rt_linked;

		if ("mon_url" in _this) _this.MO = _this.mon_url;

		if ("rew_init_bns" in _this) _this.aa = _this.rew_init_bns;
		if ("RewardsInitialBonus" in _this) _this.aa = _this.RewardsInitialBonus;

		if ("offers_p_intro_apr" in _this) _this.bT = _this.offers_p_intro_apr == "Y" ? true : false;
		if ("p_intro_apr" in _this) _this.tR = _this.p_intro_apr;
		if ("p_intro_pd" in _this && _this.p_intro_pd != null) _this.aL = _this.p_intro_pd;

		if ("OffersIntroPchApr" in _this) _this.bT = _this.OffersIntroPchApr;
		if ("PurchaseIntroAPR" in _this) _this.tR = _this.PurchaseIntroAPR || "N/A";
		if ("PurchaseIntroPeriod" in _this && _this.PurchaseIntroPeriod != null) _this.aL = _this.PurchaseIntroPeriod;

		if ("offers_bt_intro_apr" in _this) _this.fB = _this.offers_bt_intro_apr == "Y" ? true : false;
		if ("bt_intro_apr" in _this) _this.Jz = _this.bt_intro_apr;
		if ("bt_intro_pd" in _this) _this.cc = _this.bt_intro_pd;

		if ("OffersIntroBalanceTransferApr" in _this) _this.fB = _this.OffersIntroBalanceTransferApr;
		if ("BalanceTransferIntroAPR" in _this) _this.Jz = _this.BalanceTransferIntroAPR || "N/A";
		if ("BalanceTransferIntroPeriod" in _this) _this.cc = _this.BalanceTransferIntroPeriod;
		if ("BalanceTransferFee" in _this) _this.Jc = _this.BalanceTransferFee;

		if ("bt_fee" in _this) _this.Jc = _this.bt_fee;

		if ("id" in _this) _this.aM = _this.id;

		if (!_this.cs) _this.cs = "";
		if ("short_name" in _this) _this.cs = _this.short_name;

		if (!_this.ca) _this.ca = "";
		if ("name" in _this) _this.ca = _this.name;
		if ("Name" in _this) _this.ca = _this.Name;

		if ("description" in _this && angular.isString(_this.description)) {
			var tmpdesc = _this.description;
			if (tmpdesc.lastIndexOf("__") == tmpdesc.length - 2) {
				tmpdesc = tmpdesc.substring(0, tmpdesc.length - 2);
			}
			_this.ac = tmpdesc.split("__");
		} else if ("description" in _this && angular.isArray(_this.description)) _this.ac = _this.description;
		else if ("Description" in _this && angular.isString(_this.Description)) _this.ac = _this.Description.split("__");

		_this.Qc = "Qc" in _this ? _this.Qc : true;
		if ("Affiliate" in _this) _this.Qc = _this.Affiliate;

		if ("min_sec_dep" in _this) _this.bM = _this.min_sec_dep;
		if ("MinSecurityDeposit" in _this) _this.bM = _this.MinSecurityDeposit;

		if ("p_reg_apr" in _this) _this.QM = _this.p_reg_apr;
		if ("RegularPurchaseAPR" in _this) _this.QM = _this.RegularPurchaseAPR;

		if ("rewards" in _this) _this.aB = _this.rewards == "Y" ? true : false;
		if ("OffersRewards" in _this) _this.aB = _this.OffersRewards;

		if ("network" in _this) _this.tY = _this.network;

		if ("inst_name" in _this) _this.RC = _this.inst_name;
		if ("CardIssuer" in _this) _this.RC = _this.CardIssuer;

		if (!_this.xE) _this.xE = [];
		if ("rew_dt" in _this) {
			if (angular.isString(_this.rew_dt)) {
				var tmprew = _this.rew_dt;
				if (tmprew.lastIndexOf("__") == tmprew.length - 2) {
					tmprew = tmprew.substring(0, tmprew.length - 2);
				}
				_this.xE = tmprew.split("__");
			} else if (angular.isArray(_this.rew_dt)) _this.xE = _this.rew_dt;
		}
		if ("RewardsDetails" in _this && angular.isString(_this.RewardsDetails)) _this.xE = _this.RewardsDetails.split("_");

		if ("rew_redeem" in _this) _this.YA = _this.rew_redeem;

		if ("rew_cap" in _this) _this.Fs = _this.rew_cap == "Y" ? true : false;

		if ("max_late_fee" in _this) _this.Tj = _this.max_late_fee;

		if ("max_olmt_fee" in _this) _this.vc = _this.max_olmt_fee;

		if ("default_apr" in _this) _this.Ub = _this.default_apr;

		if ("cash_apr" in _this) _this.kY = _this.cash_apr;

		if ("cash_advance_fee" in _this) _this.ea = _this.cash_advance_fee;

		if ("it_fee" in _this) _this.bC = _this.it_fee;

		if ("grace_period" in _this) _this.RY = _this.grace_period;

		// get rewards code (for sorting)
		if ("rew_init_bns" in _this) _this.aa = _this.rew_init_bns;
		_this.ar = _this.initializeRewardsCode("aa");

		if ("rew_bs_earn_rt" in _this) _this.qP = _this.rew_bs_earn_rt;
		_this.bp = _this.initializeRewardsCode("qP");

		if ("rew_mx_earn_rt" in _this) _this.SN = _this.rew_mx_earn_rt;
		_this.dc = _this.initializeRewardsCode("SN");

		if ("emv_chip" in _this) _this.SMART_CHIP = _this.emv_chip;
		if ("secondary_apply" in _this) _this.SECONDARY_APPLY = _this.secondary_apply;
		else _this.SECONDARY_APPLY = null;

		if ("last_updt" in _this) _this.UPDATED_ON = _this.last_updt;

		if ("bonus_value" in _this) _this.BONUS_VALUE = _this.bonus_value;

		if ("tracking_url" in _this) {
			/** @type {string} */
			this.TRACK_URL = _this.tracking_url;
		}

		if ("bt_allowed" in _this) _this.rZ = _this.bt_allowed;

		if ("aff_inf_scope" in _this) this.Xa = _this.aff_inf_scope;

		if (!_this.ERs) _this.ERs = "";

		if ("editors_review_snippet" in _this) _this.ERs = _this.editors_review_snippet;

		if (!_this.SRf) _this.SRf = "N";

		if ("show_rates_fees" in _this) _this.SRf = _this.show_rates_fees;

		if (!_this.STy) _this.STy = "N";

		if ("show_terms_apply" in _this) _this.STy = _this.show_terms_apply;

		if (!_this.RBt) _this.RBt = "";
		if ("rew_init_bns_tooltip" in _this) _this.RBt = _this.rew_init_bns_tooltip;
		if ("internalApprovalOdds" in _this) _this.INTERNAL_APPROVAL_ODDS = _this.internalApprovalOdds;
		if ("overall_rating" in _this) _this.OVERALL_RATING = _this.overall_rating;

		return _this;
	}

	CreditCard.prototype.getDetailsPage = function () {
		if (this.bF && this.bF.indexOf("/d/") < 0) {
			return "/d/" + this.bF;
		} else {
			return this.bF;
		}
	};
	CreditCard.prototype.getRatesLink = function () {
		return "/r/?id=" + this.aM + "&rf=1";
	};

	CreditCard.prototype.getTrackLink = function () {
		return this.TRACK_URL;
	};

	CreditCard.prototype.extractNumbers = function (str) {
		if (str == null) {
			return null;
		}
		if (typeof str == "number") {
			return [str];
		}
		// convert to string
		if (str === parseInt(str, 10)) {
			str += "";
		}
		var ret = str.replace(/,/g, "").match(/[0-9]*\.?[0-9]+/g),
			i;
		if (ret == null || ret.length == 0) {
			return null;
		}
		for (i = 0; i < ret.length; i++) {
			ret[i] = parseFloat(ret[i]);
		}
		return ret;
	};

	CreditCard.prototype.initializeRewardsCode = function (property) {
		if (property in this && this[property] != null) {
			var ret = this.extractNumbers(this[property]);
			if (ret != null && ret.length > 0) {
				return ret[0];
			}
		}
		return null;
	};

	CreditCard.prototype.getRegularRate = function () {
		if (angular.isArray(this.sU)) {
			if (this.sU.length == 2) {
				return this.sU[0];
			}
		}
		return null;
	};

	CreditCard.prototype.getImageSrc = function (size) {
		var sz = "";
		if (size) sz = size + "/";

		if (this.IMAGE_NAME_FULL) return this.IMAGE_NAME_FULL;
		else if ("gW" in this) {
			this.gW = this.gW.replace("creditcards/110/", "creditcards/");
			return sz + this.gW;
		}

		return "//cdn.wallethub.com/images/searchtool/card-cover_Vfb2e043_.png";
	};

	CreditCard.prototype.hideApprovalOddsByGroupID = function () {
		// Request from Dipti to hide approval odds for all group ids
		// var groupId = pitLS.get('logout_group_id') || undefined;
		// if((groupId && ((groupId>0 && groupId<76) || (groupId>150 && groupId<226))) || this.isIssuerAmEx()){
		// if((groupId && (groupId>0 && groupId<151)) || this.isIssuerAmEx()){
		//     return true;
		// }
		// return false;
		// IP2-76939 show approval odds only for eagle data offer
		if (this.eagle_data_offer) {
			return false;
		}
		return true;
	};
	CreditCard.prototype.getMinCreditRequiredClass = function () {
		var _this = this;

		var minCredsReqd = _this.getMinCreditRequired() || "";
		var type = minCredsReqd ? minCredsReqd.toString().toLowerCase() : "",
			cls = "ultra-appr";
		if (type == "good credit") cls = "high-appr";
		else if (type == "fair credit") cls = "med-appr";
		else if (type == "bad credit") cls = "low-appr";
		else if (type !== "excellent credit") {
			cls = "limited-appr";
		}
		return cls;
	};

	CreditCard.prototype.getImageAlt = function () {
		var img_src;
		if ("gW" in this) {
			img_src = this.gW;
		} else {
			img_src = this.getName(true);
		}
		if (img_src) {
			var alt = img_src.replace(/^\s+/, "").replace(/\s+$/, "");
			alt = alt.substring(0, alt.lastIndexOf("."));
			alt = alt.replace(/[_-][0-9]+c$/, "");
			alt = alt.replace(/[^a-z0-9]/g, " ");
			return alt;
		}
		return "Card Image";
	};

	CreditCard.prototype.getStars = function () {
		var stars = [],
			rate = this.rG,
			ft = rate,
			it = parseInt(rate),
			fract = ft - it,
			i;
		for (i = 0; i < 5; i++) {
			if (i < it || (i == it && fract > 0.87)) {
				stars.push("bf-icon-star-twotone");
			} else if (i == it && fract > 0.12 && fract < 0.38) {
				stars.push("bf-icon-star-twotone-quarter");
			} else if (i == it && fract > 0.37 && fract < 0.63) {
				stars.push("bf-icon-star-twotone-half");
			} else if (i == it && fract > 0.62 && fract < 0.88) {
				stars.push("bf-icon-star-twotone-three-quarter");
			} else {
				stars.push("bf-icon-star-twotone-empty");
			}
		}
		return stars;
	};

	CreditCard.prototype.setRating = function (rate) {
		this.rG = rate;
	};
	CreditCard.prototype.getRating = function () {
		var ratio = this.rG,
			rate = ratio,
			ft = rate,
			it = parseInt(rate + ""),
			fract = ft - it,
			rating_rounded = ratio;
		if (fract <= 0.12) {
			// rounded without decimale
			rating_rounded = Math.round(ratio);
		} else if (fract > 0.12 && fract < 0.38) {
			// rounded for quarter
			rating_rounded = Math.floor(ratio * 10) / 10;
		} else if (fract > 0.37 && fract < 0.4) {
			// rounded for half
			rating_rounded = Math.ceil(ratio * 10) / 10;
		} else if (fract > 0.39 && fract < 0.63) {
			// rounded for half
			rating_rounded = Math.round(ratio * 10) / 10;
		} else if (fract > 0.62 && fract < 0.7) {
			// rounded for three quarter
			rating_rounded = Math.ceil(ratio * 10) / 10;
		} else if (fract > 0.69 && fract < 0.8) {
			// rounded for three quarter
			rating_rounded = Math.round(ratio * 10) / 10;
		} else if (fract >= 0.8 && fract < 0.88) {
			// rounded for three quarter
			rating_rounded = Math.floor(ratio * 10) / 10;
		} else {
			// rounded for full
			rating_rounded = Math.round(ratio * 10) / 10;
		}
		return rating_rounded;
	};

	CreditCard.prototype.setWHRating = function (rate) {
		this.MWR = rate;
	};
	CreditCard.prototype.getWHRating = function () {
		return this.MWR || "";
	};

	CreditCard.prototype.getVotes = function () {
		return this.vT;
	};
	CreditCard.prototype.getVotesFormatted = function () {
		return Util.Number.formatNumber(this.vT, 1);
	};
	CreditCard.prototype.getVotesNumber = function () {
		return this.vT.formatMoney(0, "");
	};
	CreditCard.prototype.setVotes = function (votes) {
		this.vT = votes;
	};

	CreditCard.prototype.isSecured = function () {
		return /secured card/i.test(this.BJ);
	};

	CreditCard.prototype.isPrepaid = function () {
		return /prepaid card/i.test(this.BJ);
	};

	CreditCard.prototype.isLimitedUse = function () {
		return this.isSecured() || /bad/i.test(this.aR);
	};

	CreditCard.prototype.getOneTimeSetupFees = function () {
		return none_if_empty(this.bU);
	};

	CreditCard.prototype.getAnnualFee = function () {
		return none_if_empty(this.Rb);
	};

	CreditCard.prototype.getInstantApproval = function () {
		return this.iA ? "Yes" : "No";
	};

	CreditCard.prototype.getMonthlyFee = function () {
		return none_if_empty(this.pU);
	};

	CreditCard.prototype.getRewardsEarnRate = function (text) {
		if (this.isLinkedRewardsRate()) {
			if (this.eR) {
				return !text ? "<span class='link' data-hm-options='{ direct : null, delay : 0 }' data-hm-tap='toggleDetails($event, card);' role='button' aria-label='" + this.eR + ". Press to see more details.'>" + this.eR + "</span>" : this.eR;
			} else {
				return "None";
			}
		}
		return none_if_empty(this.eR);
	};

	CreditCard.prototype.getRewardsBaseEarnRate = function () {
		return this.qP;
	};

	CreditCard.prototype.getRewardsMaxEarnRate = function () {
		return this.SN;
	};

	CreditCard.prototype.getRewardsInitialBonus = function () {
		return none_if_empty(this.aa);
	};

	CreditCard.prototype.getRawMinCreditRequired = /** @return {string[]} */ function () {
		var mincred = null;
		if (typeof this.aR == "string") {
			mincred = this.aR.split(/\s*,\s*/);
		} else {
			mincred = this.aR;
		}

		return mincred;
	};

	CreditCard.prototype.getMinCreditTexts = function () {
		if ("MIN_CREDIT_TEXTS" in this && typeof this.MIN_CREDIT_TEXTS == "string") {
			return this.MIN_CREDIT_TEXTS;
		}

		var mincreds = this.getRawMinCreditRequired() || [];
		var choices = ["Excellent", "Bad", "Fair", "Good", "Limited History"];
		var result = [];

		for (var i = 0; i < choices.length; i++) {
			if (mincreds.indexOf(choices[i]) > -1) {
				var mincredtext = choices[i];

				if (choices[i].indexOf("Limited") === -1) {
					mincredtext += " Credit";
				}

				result.push(mincredtext);
			}
		}

		return result.join(", ");
	};

	CreditCard.prototype.getMinCreditRequired = function (short) {
		var mincred = this.getRawMinCreditRequired(),
			choices = ["Bad", "Limited History", "Fair", "Good", "Excellent"],
			i;
		if (document.location.pathname.indexOf("no-credit") > -1) {
			choices[0] = "Limited History";
			choices[1] = "Bad";
		}
		if (!mincred) return "";
		for (i = 0; i < choices.length; i++) {
			if (mincred.indexOf(choices[i]) > -1) {
				var ret = choices[i] + (choices[i].indexOf("Limited") > -1 ? "" : " Credit");
				if (short) ret = choices[i];
				this.MIN_CREDIT_REQUIRED_PARSED = ret;
				return ret;
			}
		}
		var ret = mincred.join(", ");
		this.MIN_CREDIT_REQUIRED_PARSED = ret;
		return ret;
	};

	CreditCard.prototype.hasPurchaseIntroApr = function () {
		return this.bT && "tR" in this && this.tR != "N/A";
	};
	/*CreditCard.prototype.hasCustomPurchaseIntroApr = function() {
        if (("Tw" in this) && this.Tw) {
            return true;
        }
        return false;
    };*/
	CreditCard.prototype.getPurchaseIntroApr = function (only_intro, only_period) {
		var op = "Not Offered";
		if ("PurchaseIntroAPRText" in this && this.PurchaseIntroAPRText) {
			op = this.PurchaseIntroAPRText;
		} else if ("Tw" in this && this.Tw) {
			op = this.Tw;
		} else if (this.bT && "tR" in this && this.tR && this.tR != "N/A") {
			op = "<span>" + this.tR + "</span>";
			if (only_intro) {
				return op;
			}
			if ("aL" in this) {
				if (/^[0-9]+\s+/.test(this.aL)) {
					op += " for";
				}
				op += " ";
				if (only_period) {
					op = "";
				}
				if (/20[0-9]{2}$/.test(this.aL)) {
					op += this.aL.replace(/(20[0-9]{2})$/, "<span>$1</span>");
				} else {
					op += this.aL;
				}
			} else if (only_period) {
				return "None";
			}
		}
		return op;
	};

	CreditCard.prototype.hasBtIntroApr = function () {
		return ("BalanceTransferIntroAPRText" in this && this.BalanceTransferIntroAPRText !== "Not Offered") || (this.fB && "Jz" in this && this.Jz != "N/A");
	};

	/*CreditCard.prototype.hasCustomBtIntroApr = function() {
        if (("Pc" in this) && this.Pc) {
            return true;
        }
        return false;
    };*/

	CreditCard.prototype.isBtAllowed = function () {
		if ("rZ" in this) {
			if (this.rZ === true || this.rZ === false) {
				return this.rZ;
			}
			return /^Y$/i.test(this.rZ);
		}
		return false;
	};

	CreditCard.prototype.getBtIntroApr = function (only_intro, only_period, only_fee, no_fee) {
		var op = "Not Offered",
			show_fee = false;

		if ("BalanceTransferIntroAPRText" in this && this.BalanceTransferIntroAPRText) {
			op = this.BalanceTransferIntroAPRText;
			if (this.BalanceTransferFee && op !== "Not Offered") {
				op += "<span class='grey'>Transfer Fee:</span> <span class='grey'>";
				if ("Jc" in this && this.Jc != "None") {
					op += this.Jc;
				} else {
					op += "No";
				}
				op += "</span>";
			}
		} else if ("Pc" in this && this.Pc && !only_period && !only_fee) {
			op = this.Pc;
			if (!only_intro) show_fee = true;
		} else if (this.fB && "Jz" in this && this.Jz && this.Jz != "N/A" && this.Jz != "Not Offered") {
			op = "<span>" + this.Jz + "</span>";
			if (only_intro) {
				return op;
			}
			if ("cc" in this && !only_intro) {
				if (/^[0-9]+\s+/.test(this.cc)) {
					op += " for";
				}
				op += " ";
				if (only_period) {
					op = "";
				}
				if (/20[0-9]{2}$/.test(this.cc)) {
					op += this.cc.replace(/(20[0-9]{2})$/, "<span>$1</span>");
				} else {
					op += this.cc;
				}
			}
			if (only_period) {
				return op;
			}
			if (no_fee) {
				return op;
			}
			if (only_fee) {
				op = "";
			}
			show_fee = true;
		}
		if (show_fee) {
			op += "<span class='hide-mob'>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;</span>  <span class='grey'>Transfer Fee: ";
			if ("Jc" in this && this.Jc != "None") {
				op += this.Jc;
			} else {
				op += "No";
			}
			op += "</span>";
		}
		return op;
	};

	CreditCard.prototype.getRegularBtApr = function () {
		return this.yB || "N/A";
	};

	CreditCard.prototype.isTemplate = function (template) {
		return this.SA == template;
	};

	CreditCard.prototype.getTestTemplate = function (filters) {
		if (this.isLimitedUse() || filters.mc == "nc") {
			return "bad";
		} else if (filters.iw && filters.iw.pch) {
			return "pch";
		} else if (filters.iw && filters.iw.bt) {
			return "bt";
		} else if (filters.iw && filters.iw.reg) {
			return "reg";
		} else if (filters.iw && (filters.iw.rw || (filters.iam == "cs" && filters.nw.am) || filters.chcrd == "y" || filters.ft == "y")) {
			return "rw";
		} else {
			return "def";
		}
	};
	/** @returns {number} */
	CreditCard.prototype.getId = function () {
		return this.aM;
	};

	CreditCard.prototype.getName = function (the, small_t, short) {
		the = the || false;
		small_t = small_t || false;
		short = short || false;
		var _card_name = this.ca;
		if (short && this.cs) {
			_card_name = this.cs;
		}
		if (the) {
			if (_card_name.toLowerCase().indexOf("the ") === 0) {
				return _card_name;
			} else {
				return (small_t ? "t" : "T") + "he " + _card_name;
			}
		}
		return _card_name;
	};

	CreditCard.prototype.getNameVO = function () {
		return this.getName()
			.replace(/®|™|&reg;|&trade;/g, "")
			.replace("™", "")
			.replace("&reg;", "")
			.replace("&trade;", "");
	};

	CreditCard.prototype.getDescriptionArray = function () {
		return this.ac;
	};

	/**
	 * Whether to show the "Apply Now" button or not
	 * @param ace (Auth Cards Eligible) When a card has Xa=I and this user has ace=true
	 * then show the apply now button
	 * @returns {*}
	 */
	CreditCard.prototype.isAffiliateLink = function (ace) {
		if ("Xa" in this) {
			if (this.Xa == "O") {
				if (ace) {
					return false;
				} else {
					return this.Qc;
				}
			} else if (this.Xa == "I") {
				if (ace) {
					return this.Qc;
				} else {
					return false;
				}
			}
		}
		return this.Qc;
	};

	CreditCard.prototype.isSponsor = function () {
		return this.spnsrd && this.spnsrd == "Y";
	};

	CreditCard.prototype.getMinSecurityDeposit = function (simple) {
		var dep = this.bM;
		if (!("bM" in this) || dep == "") {
			return "None";
		}
		if (/^N\/A$/i.test(dep)) {
			return "N/A";
		}
		return !simple ? "Min Deposit of " + dep : dep;
	};

	CreditCard.prototype.getBtFee = function (text, noNA, short_link) {
		if (this.isIssuerChase() || this.isIssuerBankOfAmerica()) {
			return !text ? "<a href='' hm-tap='openDetails($event, card);' class='link'>See Details" + (short_link ? "" : " for Transfer Fee") + "</a>" : none_if_empty(this.Jc);
		}
		return noNA && this.Jc == "N/A" ? "None" : none_if_empty(this.Jc);
	};
	CreditCard.prototype.getBtApr = function () {
		var op = "Not Offered";
		if (this.fB && "Jz" in this && this.Jz != "N/A") op = this.Jz;
		return op;
	};
	CreditCard.prototype.getBtPeriod = function () {
		var op = "N/A";
		if ("cc" in this && this.cc != "None") {
			op = this.cc;
		}
		if (this.getBtApr() == "None" || !this.getBtApr() || this.getBtApr() == "Not Offered") op = "";
		return op;
	};

	CreditCard.prototype.getTestBullets = function () {
		var bullets = [],
			i;
		if (this.aB) {
			for (i = 0; i < this.xE.length; i++) {
				bullets.push(this.xE[i]);
			}
		}
		if (this.ac.length > 0) {
			for (i = 0; i < this.ac.length; i++) {
				bullets.push(this.ac[i]);
			}
		}
		bullets.push("<a href='" + this.getDetailsPage() + "' target='_blank' class='link'>More Details &amp; Reviews About " + this.getName(true) + "</span></a>");
		return bullets;
	};

	CreditCard.prototype.getRegularPurchaseApr = function () {
		return this.QM;
	};

	CreditCard.prototype.isChargeCard = function () {
		return /Charge Card/i.test(this.BJ);
	};

	CreditCard.prototype.hasRewards = function () {
		return this.aB;
	};

	CreditCard.prototype.getNetwork = function () {
		return this.tY;
	};

	CreditCard.prototype.getIssuer = function () {
		return this.RC;
	};

	CreditCard.prototype.getRewards = function () {
		return this.xE;
	};

	CreditCard.prototype.hasEditorsReviewSnippet = function () {
		return this.ERs && this.ERs.trim() != "";
	};

	CreditCard.prototype.getEditorsReviewSnippet = function (more) {
		if (!this.ERs) return "";
		var review = this.ERs.trim();
		if (review.endsWith(".") && more) {
			review = review.slice(0, -1);
		}
		return review != "" ? review + (more ? " ... <a href='" + this.getDetailsPage() + "' target='_blank' class='link link-grey' rel='nofollow'>show more</a>" : "") : "";
	};

	CreditCard.prototype.hasInitialBonusTooltip = function () {
		return this.RBt && this.RBt.trim() != "";
	};

	CreditCard.prototype.getInitialBonusTooltip = function () {
		if (!this.RBt) return "";
		var review = this.RBt.trim();
		return review;
	};

	// Possible values for pros and cons source: System,Custom,System_Editorial,Custom_Editorial,None

	CreditCard.prototype.hasPros = function () {
		if (this.EPS && this.EPS.toUpperCase() == "SYSTEM" && this.EPs && this.EPs.length > 0) {
			return true;
		} else if (this.EPS && this.EPS.toUpperCase() == "CUSTOM" && this.EP && this.EP.length > 0) {
			return true;
		} else {
			return false;
		}
	};

	CreditCard.prototype.hasCons = function () {
		if (this.ECS && this.ECS.toUpperCase() == "SYSTEM" && this.ECs && this.ECs.length > 0) {
			return true;
		} else if (this.ECS && this.ECS.toUpperCase() == "CUSTOM" && this.EC && this.EC.length > 0) {
			return true;
		} else {
			return false;
		}
	};

	CreditCard.prototype.getPros = function () {
		if (this.EPS && this.EPS.toUpperCase() == "SYSTEM" && this.EPs && this.EPs.length > 0) {
			return this.EPs;
		} else if (this.EPS && this.EPS.toUpperCase() == "CUSTOM" && this.EP && this.EP.length > 0) {
			return this.EP;
		} else {
			return [];
		}
	};

	CreditCard.prototype.getCons = function () {
		if (this.ECS && this.ECS.toUpperCase() == "SYSTEM" && this.ECs && this.ECs.length > 0) {
			return this.ECs;
		} else if (this.ECS && this.ECS.toUpperCase() == "CUSTOM" && this.EC && this.EC.length > 0) {
			return this.EC;
		} else {
			return [];
		}
	};

	CreditCard.prototype.getRwardsType = function () {
		return this.YA;
	};

	CreditCard.prototype.isRewardCap = function () {
		return this.Fs;
	};

	CreditCard.prototype.getMaxLateFee = function () {
		return this.Tj;
	};

	CreditCard.prototype.getMaxOverlimitFee = function () {
		return this.vc;
	};

	CreditCard.prototype.getDefaultApr = function () {
		return this.Ub;
	};

	CreditCard.prototype.getCashApr = function () {
		return this.kY;
	};

	CreditCard.prototype.getCashAdvanceFee = function () {
		return this.ea;
	};

	CreditCard.prototype.getForeignTransactionFee = function () {
		return this.bC;
	};

	CreditCard.prototype.getGracePeriod = function () {
		return this.RY;
	};

	CreditCard.prototype.americanExpressWithMonitoringUrl = function () {
		return this.RC == "American Express" && "MO" in this && this.MO != "";
	};

	CreditCard.prototype.HSBCWithMonitoringUrl = function () {
		return (this.RC == "HSBC" || (this.RC + "").indexOf("Discover") === 0 || this.RC == "Barclays" || this.RC == "Wells Fargo" || this.RC == "U.S. Bank" || this.RC == "Marcus by Goldman Sachs") && "MO" in this && this.MO != "";
	};

	CreditCard.prototype.isIssuerChase = function () {
		return /Chase/i.test(this.RC);
	};

	CreditCard.prototype.isIssuerBankOfAmerica = function () {
		return this.RC == "Bank of America";
	};

	CreditCard.prototype.isLinkedRewardsRate = function () {
		if (typeof this.Wz == "boolean") {
			return this.Wz;
		} else if (this.Wz) {
			return this.Wz.toUpperCase() == "Y";
		}
		return false;
	};

	CreditCard.prototype.isIssuerAmEx = function () {
		return this.RC == "American Express";
	};
	/**
	 *
	 * @param {{skip:string[]}} [opts]
	 */
	CreditCard.prototype.hasRates = function (opts) {
		var show_rates = false;
		if (typeof this.SRf == "boolean") {
			show_rates = this.SRf;
		} else if (this.SRf) {
			show_rates = this.SRf.toUpperCase() == "Y";
		}
		var condition = (this.aM || "").toString() == "2156" || (this.aM || "").toString() == "1667" || (this.aM || "").toString() == "3292" ? true : false;

		if (opts && opts.skip) {
			if (opts.skip.indexOf("american") > -1) condition = condition && !this.americanExpressWithMonitoringUrl() ? true : false;
			if (opts.skip.indexOf("hsbc") > -1) condition = condition && !this.HSBCWithMonitoringUrl() ? true : false;
		} else condition = this.americanExpressWithMonitoringUrl() || this.HSBCWithMonitoringUrl() || condition || show_rates ? true : false;

		return condition;
	};

	CreditCard.prototype.hasTerms = function () {
		var show_term = false;
		if (typeof this.STy == "boolean") {
			show_term = this.STy;
		} else if (this.STy) {
			show_term = this.STy.toUpperCase() == "Y";
		}

		var condition = show_term || this.americanExpressWithMonitoringUrl() ? true : false;
		return condition;
	};

	CreditCard.prototype.ApprovalOds = /** @param  {number} [groupId] */ function (groupId) {
		var type = this.ApprovalOdds ? this.ApprovalOdds.toString().toLowerCase() : "",
			cls = "ultra-appr";
		if (type == "very good") cls = "high-appr";
		else if (type == "good") cls = "med-appr";
		else if (type == "fair") cls = "low-appr";
		else if (type !== "excellent" && type !== "pre-selected" && type !== "pre-approved" && type !== "outstanding") {
			cls = "limited-appr";
		}
		return {
			text: this.ApprovalOdds,
			cls: cls,
		};
	};

	CreditCard.prototype.hasApprovalOds = function () {
		return "ApprovalOdds" in this && this.ApprovalOdds !== undefined && this.ApprovalOdds !== null && !this.isIssuerAmEx();
	};

	CreditCard.prototype.getApprovalOdds = function (vantageScore) {
		if (this.hasApprovalOds()) {
			return this.ApprovalOdds;
		}

		return "N/A";
		/*
        var mincred = this.getMinCreditRequired().replace(/\s+Credit$/, ""),
            matrix = {};
        if (mincred == "Limited History") {
            mincred = "Limited";
        }
        if(!mincred) return "N/A";

        if (vantageScore >= 795) {
            matrix = {
                "Excellent": "Excellent",
                "Good": "Excellent",
                "Fair": "Excellent",
                "Limited": "Excellent",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 765 && vantageScore < 795) {
            matrix = {
                "Excellent": "Very Good",
                "Good": "Excellent",
                "Fair": "Excellent",
                "Limited": "Excellent",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 750 && vantageScore < 765) {
            matrix = {
                "Excellent": "Good",
                "Good": "Very Good",
                "Fair": "Excellent",
                "Limited": "Excellent",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 735 && vantageScore < 750) {
            matrix = {
                "Excellent": "Poor",
                "Good": "Very Good",
                "Fair": "Very Good",
                "Limited": "Very Good",
                "Bad": "Very Good"
            };
        } else if (vantageScore >= 720 && vantageScore < 735) {
            matrix = {
                "Excellent": "Low",
                "Good": "Very Good",
                "Fair": "Excellent",
                "Limited": "Excellent",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 700 && vantageScore < 720) {
            matrix = {
                "Excellent": "Low",
                "Good": "Good",
                "Fair": "Excellent",
                "Limited": "Excellent",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 685 && vantageScore < 700) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Very Good",
                "Limited": "Very Good",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 665 && vantageScore < 685) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Good",
                "Limited": "Good",
                "Bad": "Excellent"
            };
        } else if (vantageScore >= 640 && vantageScore < 665) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Fair",
                "Limited": "Fair",
                "Bad": "Very Good"
            };
        } else if (vantageScore >= 620 && vantageScore < 640) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Low",
                "Limited": "Low",
                "Bad": "Very Good"
            };
        } else if (vantageScore >= 570 && vantageScore < 620) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Low",
                "Limited": "Low",
                "Bad": "Good"
            };
        } else if (vantageScore >= 300 && vantageScore < 570) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Low",
                "Limited": "Low",
                "Bad": "Fair"
            };
        } else if (vantageScore == 4 || !vantageScore) {
            matrix = {
                "Excellent": "Low",
                "Good": "Low",
                "Fair": "Low",
                "Limited": "Good",
                "Bad": "Very Good"
            };
        }
        if (mincred in matrix) {
            return matrix[mincred];
        }
        return "N/A";
         */
	};

	// get approval odds for cc searchtools
	CreditCard.prototype.ApprovalOdsCCSearchtools = /** @param  {number} [groupId] */ function (vantageScore, groupId) {
		var appr_odds = this.getApprovalOdds(vantageScore);
		var type = appr_odds ? appr_odds.toString().toLowerCase() : "";
		var cls = "ultra-appr";
		if (type == "very good") cls = "high-appr";
		else if (type == "good") cls = "med-appr";
		else if (type == "fair") cls = "low-appr";
		else if (type !== "excellent") {
			cls = "limited-appr";
		}
		return {
			text: appr_odds,
			cls: cls,
		};
	};

	CreditCard.prototype.getOverlimit = function () {
		return this.vc;
	};

	CreditCard.prototype.getLateFee = function () {
		return this.Tj;
	};
	CreditCard.prototype.getSmartChip = function () {
		return this.SMART_CHIP;
	};
	CreditCard.prototype.getUpdateDate = function () {
		return this.UPDATED_ON;
	};
	CreditCard.prototype.getActivationFee = function () {
		return this.act_fee || "None";
	};
	CreditCard.prototype.getSignatureFee = function () {
		return this.sig_txn_fee || "Free";
	};
	CreditCard.prototype.getPINFee = function () {
		return this.pin_txn_fee || "Free";
	};
	CreditCard.prototype.getInATMFee = function () {
		return this.atm_fee_in || "$0";
	};
	CreditCard.prototype.getATMSize = function () {
		return this.in_network_atms_num;
	};
	CreditCard.prototype.getOutATMFee = function () {
		return this.atm_fee || "$0";
	};
	CreditCard.prototype.getForeignATMFee = function () {
		return this.international_txn_fee;
	};
	CreditCard.prototype.getLiveSupport = function () {
		return this.live_cust_svc || "Free";
	};
	CreditCard.prototype.getAutoSupport = function () {
		return this.auto_cust_svc || "Free";
	};
	CreditCard.prototype.getReloadOptions = function () {
		return this.reload_networks;
	};
	CreditCard.prototype.getCancelFee = function () {
		return this.cancel_fee || "Free";
	};
	CreditCard.prototype.getInactivityFee = function () {
		return this.inact_fee || "None";
	};

	CreditCard.prototype.setAdID = function (id) {
		this.ADID = id;
	};
	CreditCard.prototype.getAdID = function () {
		return this.ADID;
	};

	CreditCard.prototype.getBonusValue = function () {
		return this.BONUS_VALUE;
	};

	/** @type { CreditCard } */
	CreditCard.TYPE = null;

	return CreditCard;
});

var obfuscate = "cc";

/**
 * Use the line above as the first line of any JS code when you wish to inform the post-commit hook that we need to obfuscate credit card fields in the minified version.
 * Note that the line above will be removed in the obfuscated version.
 */
define("ccModel", ["ith-ccModel","ccFilters", "angular"], function (CreditCard,$filters, angular) {

    var sc_regex = /Secured Card/i,
        st_regex = /Store Card/i,
        ch_regex = /Charge Card/i,
        na_regex = /N\/A/i,
        no_regex = /None/i,
        pt_regex = /(\d+)%/,
        cha_regex = {
            a: /Health & Social Causes/i,
            b: /Nature & Wildlife Causes/i
        };

    for (var i in $filters) {
        if (["v", "defaults"].indexOf(i) > -1) {
            continue;
        }
        for (var j in $filters[i]) {
            // fix regex in filter data
            if ($filters[i][j].regex != null && typeof $filters[i][j].regex == "string") {
                $filters[i][j].regex = new RegExp($filters[i][j].regex, "i");
            }
        }
    }

    CreditCard.prototype.filterCardClassification = function (iam) {
        if (this.Nb == null) {
            return true;
        }
        return $filters.iam[iam].regex.test(this.Nb);
    };

    CreditCard.prototype.filterCreditType = function (mc) {
        if (mc == null) {
            return true;
        }
        return $filters.mc[mc].regex.test(this.aR);
    };

    CreditCard.prototype.filterNetwork = function (nw, storecard) {
        if (storecard) {
            return st_regex.test(this.tY);
        } else {
            for (var i in nw) {
                if (nw[i] && $filters.nw[i].regex.test(this.tY)) {
                    return true;
                }
            }
        }
        return false;
    };

    CreditCard.prototype.filterIssuer = function (inst, inst_o, pristine, other_issuer) {
        // filters are untouched, return all
        if (pristine) {
            return true;
        }
        // only "Other" is checked, and we need to query a specific issuer
        if (other_issuer != null) {
            return this.RC != null && this.RC.toLowerCase() == other_issuer.toLowerCase();
        }
        // if other is checked
        if (inst_o && this.iC == -1) {
            return true;
        }
        // try to match checked checkboxes
        for (var i = 0; i < inst.length; i++) {
            if (inst[i].checked && inst[i].code == this.iC) {
                return true;
            }
        }
        return false;
    };

    CreditCard.prototype.filterCardSecurity = function (iws) {
        if (iws.sc && iws.us) {
            return true;
        }
        return sc_regex.test(this.BJ) == iws.sc;
    };

    CreditCard.prototype.filterPurchaseIntroApr = function () {
        if (this.bT) {
            return (this.tR + "").indexOf("0%") === 0;
        }
        return false;
    };

    CreditCard.prototype.filterBtIntroApr = function () {
        if (this.rZ) {
            return (this.Jz + "").indexOf("0%") === 0;
        }
        return false;
    };

    CreditCard.prototype.filterInterestRate = function (regval) {
        var interest = this.getRegularRate();
        if (interest != null) {
            return interest <= regval;
        }
        return false;
    };

    CreditCard.prototype.filterRewards = function (rw) {
        if (this.aB) {
            for (i in rw) {
                if (rw[i]) {
                    if (["cb", "mi", "pt"].indexOf(i) > -1 && $filters.rw[i].regex.test(this.YA)) {
                        return true;
                    }
                    if (i == "gas" && $filters.rw[i].regex.test(this.Sz)) {
                        return true;
                    }
                    if (i == "ho" && $filters.rw[i].regex.test(this.zQ)) {
                        return true;
                    }
                }
            }
        }
        return false;
    };

    CreditCard.prototype.filterBalanceTransferFee = function (bt, bt_all_true) {
        if (bt_all_true || (this.rZ && no_regex.test(this.Jc))) {
            return true;
        } else if (na_regex.test(this.Jc)) {
            return false;
        }
        if (this.rZ && !na_regex.test(this.Jc)) {
            var matches = (this.Jc + "").match(pt_regex),
                num;
            if (matches) {
                num = matches[1];
                if ((bt.bt3 && num > 0 && num < 4) || (bt.bt4 && num >= 4 && num < 5) || (bt.bt5 && num >= 5)) {
                    return true;
                }
            }
        }
        return false;
    };

    CreditCard.prototype.filterEmvChip = function (emv, emv_all_true) {
        if (emv_all_true) {
            return true;
        }
        if (emv.n && (!this.eC || /No/i.test(this.eC))) {
            return true;
        }
        if (/Yes/i.test(this.eC)) {
            if (emv.pn && /PIN/i.test(this.eC)) {
                return true;
            }
            if (emv.sg && (/signature/i.test(this.eC) || /unknown/i.test(this.eC))) {
                return true;
            }
        }
        return false;
    };

    CreditCard.prototype.filter = function (filters) {
        if (filters.chcrd != "y") {
            if (!this.filterCreditType(filters.mc)) {
                return false;
            }
            if (!this.filterNetwork(filters.nw, filters.stcrd == "y")) {
                return false;
            }
        }
        if (!this.filterCardClassification(filters.iam)) {
            return false;
        }
        if (filters.chcrd == "y") {
            return ch_regex.test(this.BJ);
        }
        if (!this.filterIssuer(filters.inst, filters.inst_o, filters.inst_pristine, filters.other_issuer)) {
            return false;
        }
        if (filters.iws.sc || filters.iws.us) {
            return this.filterCardSecurity(filters.iws);
        }
        if (filters.iw.pch && !this.filterPurchaseIntroApr()) {
            return false;
        }
        if (filters.iw.bt && !this.filterBtIntroApr()) {
            return false;
        }
        if (filters.iw.reg && !this.filterInterestRate(filters.reg)) {
            return false;
        }
        if (filters.iw.rw && !this.filterRewards(filters.rw)) {
            return false;
        }
        if (filters.iw.af && !this.nA) {
            return false;
        }
        if (!this.filterBalanceTransferFee(filters.bt, filters.bt_all_true)) {
            return false;
        }
        if (filters.ft == "y" && !no_regex.test(this.bC)) {
            return false;
        }
        if (filters.pic == "y" && !this.ba) {
            return false;
        }
        if (filters.cha == "y" && !cha_regex.a.test(this.zQ) && !cha_regex.b.test(this.zQ)) {
            return false;
        }
        if (!this.filterEmvChip(filters.emv, filters.emv_all_true)) {
            return false;
        }
        return true;
    };

    CreditCard.prototype.getImageSrc = function (size) {

        if (this.visible) {
            size = "";
        }

        var sz = "";
        if(size) sz=size+"/";

        if ("gW" in this) {
            return require.toUrl("cdn") + "product/images/creditcards/" +sz+ this.gW;
        }
        return "//cdn.wallethub.com/images/searchtool/card-cover_Vfb2e043_.png";
    };

    CreditCard.prototype.getApplyLink = function() {

        var m = (document.cookie + "").match(/(?:^|;)\s*ccstv=([^;]+)/),
            v = null;
        if (m && m.length > 1) {
            v = m[m.length - 1];
        }
        if (v === null) {
            v = "0";
        }

        return "/r/?id=" + this.getId() + "c&v=" + v + "&ref=" + encodeURIComponent(document.location.pathname + document.location.search);

    };

    return CreditCard;

});

//@ts-check
/// <reference path="./../../mywallet/declarations.d.ts" />
var obfuscate = "cc";

/**
 * Use the line above as the first line of any JS code when you wish to inform the post-commit hook that we need to obfuscate credit card fields in the minified version.
 * Note that the line above will be removed in the obfuscated version.
 */
//@ts-ignore
define('stModule',["require", "page", "stApp", "ccFilters", "pitLS", "ccModel", "cookie-helper", "angular", "polyfills"], function (require) {
	/** @type {typeof import("ithModules").Tools} */
	var Util = require("polyfills");
	/** @type {import("ithModules").Angular} */
	var angular = require("angular");
	/** @type {JQueryStatic} */
	//@ts-ignore
	var $ = angular.element;
	/** @type {import("ithModules").App} */
	var app = require("stApp");
	/** @type {{[key:string]:any}} */
	var $filters = require("ccFilters");
	/** @type {{[key:string]:any}} */
	var cookie = require("cookie-helper");
	/** @type {{[key:string]:any}} */
	var page = require("page");
	/** @type {typeof import("./../../mywallet/cc-model")} */
	var CreditCard = require("ccModel");
	/** @type {import("ithModules").Storage} */
	var pitLS = require("pitLS");

	// switch to mywallet suffix
	pitLS.group("mw");

	/**
	 * A/B header test
	 * ------------------------------
	 * testid conditions:
	 * 1-33 show new design with sticky filters on desktop
	 * 34-66 show new design without sticky filters on desktop
	 * 67-100 show current design
	 */
	var testid = parseInt(cookie.read("testid"));
	if (isNaN(testid)) {
		testid = 51;
	}
	//if(testid<51) $("#bgt").addClass("white");
	// end the experiment : IP2-77749
	// if(testid>66) $("body").removeClass("curi-top-filters");
	// end the experiment : IP2-77428
	// if(testid<51) $("body").removeClass("with-pros-cons");

	//IP2-82817 end experiment
	// if (testid<51) $("body").addClass("card-template-a").removeClass("card-template-b");
	// else $("body").addClass("card-template-b").removeClass("card-template-a");

	// if (testid<31) $("body").addClass("cc-list-off").removeClass("cc-list-on");
	// else $("body").addClass("cc-list-on").removeClass("cc-list-off");
	// end experiment
	// $("body").addClass("cc-list-on").removeClass("cc-list-off");

	// if(testid>50) $("body").addClass("grid-card");
	// if(testid<51) $("body").removeClass("grid-card");
	/**
	 * CC back intercept
	 * ------------------------------
	 * testid conditions:
	 * 1-10 overlay best cards
	 * 11-45 no overlay
	 * 46-65 overlay best cards
	 * 66-100 overlay with both links
	 */
	function ccbi_show() {}
	$("#viewport > footer.footer .main a, .related-links a, .sub-menu a, .tab-navbar a").on("click", function () {
		//@ts-ignore
		var _url = $(this).attr("href");
		window.open(_url, "_self");
		return false;
	});
	$("#viewport").on("click", ".related-links a", function () {
		//@ts-ignore
		var _url = $(this).attr("href");
		window.open(_url, "_self");
		return false;
	});
	angular.forEach($(".cardhub-edu-table"), function (element) {
		//@ts-ignore
		if (!$(element).parent().is(".cardhub-edu-table-div")) {
			$(element).wrap('<div class="cardhub-edu-table-div" />');
		}
	});
	// $("body").on("mouseleave", function (e) {
	//     var testid = parseInt(cookie.read("testid")),
	//         ccbi_n = "__wh_ccbi",
	//         ccbi = cookie.read(ccbi_n),
	//         bi = $(".back-intercept");
	//     if (isNaN(testid)) {
	//         testid = -1;
	//     }
	//     if ((testid > 10 && testid < 46) || e.clientY > 0 || ccbi != null) {
	//         return;
	//     }
	//     bi.addClass("show");
	//     cookie.create(ccbi_n, new Date().getTime());
	//     if ((testid > -1 && testid < 11) || (testid > 45 && testid < 66)) {
	//         bi.find(".action-extra").remove();
	//     }
	// });
	// $(".back-intercept").on("click", ".btn-close,.back-intercept-overlay", function () {
	//     $(".back-intercept").removeClass("show");
	// });
	// eof back intercept
	var $document = $(document),
		$arrow_element = $("#global-arrow-up"),
		className = "show";
	//@ts-ignore
	$document.scroll(function () {
		//@ts-ignore
		if ($document.scrollTop() >= 1800) {
			$arrow_element.addClass(className);
			$arrow_element.attr("tabindex", "0");
			$arrow_element.attr("aria-hidden", "false");
		} else {
			$arrow_element.removeClass(className);
			$arrow_element.attr("tabindex", "-1");
			$arrow_element.attr("aria-hidden", "true");
		}
		// sticky filters IP2-76273
		// it's only applied for test id 1-33
		// if(testid<34){
		//     //@ts-ignore
		//     var bodyscroll = $document.scrollTop(),
		//         body = angular.element().cssSelect("body"),
		//         parentWidth = body.prop("clientWidth"),
		//         ftr = angular.element().cssSelect("#searchtool .extra-content-desktop"),
		//         crds = angular.element().cssSelect("#searchtool .card-area-box"),
		//         //@ts-ignore
		//         min = crds.offset().top,
		//         width = crds.prop("offsetWidth"),
		//         cardsHeight = crds.prop("offsetHeight"),
		//         max = min+cardsHeight,
		//         //@ts-ignore
		//         left = crds.offset().left,
		//         right = parentWidth - (left + width),
		//         top = 55 + window["headerTransit"];
		//     if((bodyscroll+top)>min && (bodyscroll+top)<max){
		//         body.addClass("sticky-filters");
		//         ftr.css("top", top+"px");
		//         ftr.css("left", left+"px");
		//         ftr.css("right", right+"px");
		//     }else{
		//         body.removeClass("sticky-filters");
		//         ftr.css("top", "auto");
		//         ftr.css("left", "auto");
		//         ftr.css("right", "auto");
		//     }
		// }
	});
	$arrow_element.on("click", function () {
		//@ts-ignore
		$("html,body").animate(
			{
				scrollTop: 0,
			},
			300
		);
		setTimeout(function () {
			//@ts-ignore
			$.get("/gototop.png", {});
		}, 300);
	});
	/**
	 * Returns true for objects like:
	 * {foo: true, bar: true}
	 * {foo: {checked: true}, bar: {checked: true}}
	 */
	function all_true(obj) {
		for (var i in obj) {
			if (typeof obj[i] == "boolean" && !obj[i]) {
				return false;
			} else if (typeof obj[i] == "object") {
				if ("checked" in obj[i] && typeof obj[i].checked == "boolean") {
					if (!obj[i].checked) {
						return false;
					}
				} else {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * Returns true for objects like:
	 * {foo: false, bar: false}
	 * {foo: {checked: false}, bar: {checked: false}}
	 */
	function all_false(obj) {
		for (var i in obj) {
			if (typeof obj[i] == "boolean" && obj[i]) {
				return false;
			} else if (typeof obj[i] == "object") {
				if ("checked" in obj[i] && typeof obj[i].checked == "boolean") {
					if (obj[i].checked) {
						return false;
					}
				} else {
					return false;
				}
			}
		}
		return true;
	}

	function array_diff(arr1, arr2) {
		var diff = [],
			i = arr1.length,
			elm;
		while (i--) {
			elm = arr1[i];
			if (arr2.indexOf(elm) === -1) {
				diff.push(elm);
			}
		}
		return diff.reverse();
	}

	var userAgent = navigator.userAgent;
	var platform = navigator.platform ? navigator.platform : "";

	function isAndroid() {
		return userAgent.match(/Android/i) != null || (platform && platform.match(/Android/i) != null);
	}

	// special directive for adding reviews to cards, its completely dependent of how the html markup has been made, not suitable for general use
	app.register.directive("reviewStars", [
		"$timeout",
		"$http",
		function ($timeout, $http) {
			var rating = ["Bad", "Below Average", "Average", "Good", "Excellent"],
				// - tracking cookie
				guid = (function () {
					function s4() {
						return Math.floor((1 + Math.random()) * 0x10000)
							.toString(16)
							.substring(1);
					}
					return function () {
						return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
					};
				})();

			if (!pitLS.get("rate_tracking")) {
				pitLS.set("rate_tracking", guid());
			}

			var votes = pitLS.get("card-votes");
			if (!angular.isObject(votes)) {
				votes = {};
			}

			return {
				restrict: "A",
				link: /** @param {ng.IScope & {[key:string]:any}} $scope */ function ($scope, _el, attrs) {
					var card = $scope.$eval(attrs.reviewStars),
						org_stars = card.getStars(),
						star_cls = ["bf-icon-star-twotone", "bf-icon-star-twotone-half", "bf-icon-star-twotone-empty"],
						outTimer,
						tooltipTimer,
						votedTimer,
						saved_vote = null,
						i;

					$scope.stars = org_stars.slice(0);
					$scope.rate = card.getRating();
					$scope.rating = "";
					$scope.reviews = card.getVotes();

					if (card.aM in votes) {
						saved_vote = votes[card.aM];
					}

					$scope.rateHeading = angular.isNumber(saved_vote) ? "" : "Rating:";
					$scope.show_tip = false;

					$scope.voted = saved_vote;
					$scope.voted_index = false;
					$scope.keep_existing = false;
					$scope.just_voted = false;

					$scope.track = function (_$event, index, method) {
						if ($scope.just_voted) {
							return false;
						}
						if (method == "add") {
							for (i = 0; i < org_stars.length; i++) {
								if (i <= index) {
									$scope.stars[i] = star_cls[0];
								} else {
									$scope.stars[i] = star_cls[2];
								}
							}

							if (angular.isNumber($scope.voted_index)) {
								saved_vote = $scope.voted_index;
							}

							if (angular.isNumber(saved_vote)) {
								$scope.stars[saved_vote] = star_cls[0];
							}

							$scope.just_voted = false;
							$scope.rateHeading = "";
							$scope.keep_existing = saved_vote === index;
							$scope.rating = rating[index];
							$timeout.cancel(outTimer);
							$scope.show_tip = true;
							$timeout.cancel(tooltipTimer);
						} else {
							outTimer = $timeout(function () {
								for (i = 0; i < org_stars.length; i++) {
									$scope.stars[i] = org_stars[i];
								}
							});
							tooltipTimer = $timeout(function () {
								if (!$scope.just_voted) {
									$scope.show_tip = false;
								}
							}, 1000);
						}
					};

					$scope.inPopup = function (_$event, method) {
						if (method == "over") {
							$scope.show_tip = true;
							$timeout.cancel(tooltipTimer);
						} else {
							tooltipTimer = $timeout(function () {
								$scope.show_tip = false;
							}, 100);
						}
					};

					$scope.voting = false;

					$scope.rateCard = function (_$event, $index) {
						if ($scope.voting) {
							return;
						}
						$timeout.cancel(votedTimer);
						$scope.voting = true;
						var votes = pitLS.get("card-votes") || {};
						$http({
							url: "/ajax.php",
							method: "POST",
							data: {
								action: "Details.SetRate",
								rtg: $index + 1,
								uri: window.location.origin + card.getDetailsPage(),
								tracker: pitLS.get("rate_tracking"),
							},
						}).then(function (response) {
							var dt = response.data;
							$scope.voting = false;
							if (dt.error) {
								if (dt.type == "rtg-hasreview") {
									$scope.voted = true;
									$scope.rateHeading = "Thanks for your rating!";
									votes[card.aM] = $index;
									pitLS.set("card-votes", votes);
								}
							} else if (dt.guest && dt.redirect) {
								if (dt.redirect == "self") {
									dt.redirect = "/join/light?ref=" + escape(window.location.href);
								}
								window.location.href = dt.redirect;
							} else {
								$scope.voted = true;
								$scope.rateHeading = "Thanks for your rating!";
								$scope.voted_index = $index;
								votes[card.aM] = $index;
								pitLS.set("card-votes", votes);
								card.setRating(dt.rating);
								$scope.stars = card.getStars();
								$scope.rate = card.getRating();
								org_stars = card.getStars();
								$scope.just_voted = true;
								$scope.rating = "";
								card.setVotes(dt.total);
								$scope.reviews = card.getVotes();
								$scope.keep_existing = false;
								$scope.show_tip = true;
								votedTimer = $timeout(function () {
									$scope.just_voted = false;
									$scope.show_tip = false;
								}, 3000);
							}
						});
					};
					if (!$scope.just_voted) {
						$scope.show_tip = false;
					}
				},
			};
		},
	]);

	app.register.controller("SearchToolCardsController", [
		"$scope",
		"$injector",
		function ($scope, $injector) {
			/** @type { { showCreditPopup(state:boolean): void, ccFiltersReady(): void, setIntro: (intro: { top?: string; btm?: string; title?:string, headline?:string, filtername?:string }) => void, onFiltersSet :(handler:(name:string,value:any )=>void)=>void, myStanding:string, myScore:number,  isSessionActive: boolean, hasCreditFilter: boolean, loggedInData: {[key:string]:any} } } */
			var $stService = $injector.get("$stService");
			$scope.selected_credit_text = "My credit";

			var isSessionActive = $stService.isSessionActive;
			var loggedInData = $stService.loggedInData;

			var thinfile = false;
			if (loggedInData.hasOwnProperty("standing") && loggedInData.standing == "Thinfile") {
				thinfile = true;
			}
			if (loggedInData.hasOwnProperty("thinfile") && loggedInData.thinfile === true) {
				thinfile = true;
			}

			var standingInvalid = false;
			if (Util.isAnyOf(loggedInData.standing, ["Invalid", "FileSuppressed", "InvalidVendorRequest", "Thinfile", "OutOfRange", "Deceased"])) {
				standingInvalid = true;
			}

			var $root = $injector.get("$rootScope");
			var $http = $injector.get("$http"),
				$timeout = $injector.get("$timeout"),
				$location = $injector.get("$location"),
				$url = $injector.get("$url"),
				$window = $injector.get("$window"),
				$viewport = $injector.get("$viewport"),
				$q = $injector.get("$q"),
				$httpParamSerializer = $injector.get("$httpParamSerializer");
			$scope.show_best_menu = false;
			$scope.ShowBestCardMenu = function ($event, $show) {
				setTimeout(function () {
					$scope.$applyAsync(function () {
						$scope.show_best_menu = $show;
					});
				}, 50);
			};
			$root.tooltips = {
				loggedIn: "<p class='logged-in-tooltip'>Since you are logged into WalletHub, we filtered the cards on this page based on your latest credit score.</p>",
				minCred:
					"" +
					"<div class='table-container'> " +
					"<div class='row'> " +
					"<div class='white'></div> " +
					"<div class='grey' tabindex='0'>Credit Score</div> " +
					"</div>" +
					"<div class='row' role='text' tabindex='0' ng-aria-labelledby=\"::'_self_split'\"> " +
					"<div class='grey'>Excellent Credit</div> " +
					"<div class='white'>750 \u2014 850</div> " +
					"</div> " +
					"<div class='row' role='text' tabindex='0' ng-aria-labelledby=\"::'_self_split'\"> " +
					"<div class='grey'>Good Credit</div> " +
					"<div class='white'>700 \u2014 749</div> " +
					"</div> " +
					"<div class='row' role='text' tabindex='0' ng-aria-labelledby=\"::'_self_split'\"> " +
					"<div class='grey'>Fair Credit</div> " +
					"<div class='white'>640 \u2014 699</div> " +
					"</div> " +
					"<div class='row' role='text' tabindex='0' ng-aria-labelledby=\"::'_self_split'\"> " +
					"<div class='grey'>Bad Credit</div> " +
					"<div class='white'>300 \u2014 639</div> " +
					"</div> " +
					"<div class='row' role='text' tabindex='0' ng-aria-labelledby=\"::'_self_split'\"> " +
					"<div class='grey'>Limited Credit</div> " +
					"<div class='white'>Less than 3 years of credit history</div> " +
					"</div> " +
					"</div>" +
					"<strong tabindex='0'>Get Your Free Credit Score</strong> " +
					"<p tabindex='0'>Join WalletHub and get your credit score. It&rsquo;s 100% free, forever.</p> " +
					"<a tabindex='0' href='/join/' hm-url target='_blank' class='btn blue no-decoration'>Get your free credit score now</a><br/><br/><p style='color:#5D7279;font-size:13px'>The credit score shown on WalletHub is based on your TransUnion credit report as well as the VantageScore 3.0 model, and it may differ from what your lender or insurer uses.</p>",
				approvalOdds:
					"<strong>&dagger;Approval Odds</strong> are WalletHub estimates intended to gauge your likelihood of approval for a particular product. Approval Odds are based on WalletHub data and are not provided or endorsed by the lender. Approval Odds are not meant to imply or guarantee that you will be approved by the lender or that credit will be extended. WalletHub may share your information with third-parties in order to show personalized offers, as well as enable you to interact more easily with pre-fill forms or applications. You can opt-out of sharing your personal info <a class='link' href='/home/settings/private-info' target='_blank' data-hm-url>here</a>.",
				author: "<strong>&dagger;Approval Odds</strong> are WalletHub estimates intended to gauge your likelihood of approval for a particular product. Approval Odds are based on WalletHub data and are not provided or endorsed by the lender. Approval Odds are not meant to imply or guarantee that you will be approved by the lender or that credit will be extended. WalletHub may share your information with third-parties in order to show personalized offers, as well as enable you to interact more easily with pre-fill forms or applications. You can opt-out of sharing your personal info <a class='link' href='/home/settings/private-info' target='_blank' data-hm-url>here</a>.",
			};
			$root.show_ask_overlay = false;

			var testid = parseInt(cookie.read("testid"));
			if (isNaN(testid)) {
				testid = 1;
			}

			$scope.is_android = isAndroid();

			function cardAdPrepare(card, is_pop) {
				var clickid = Util.uniqid(),
					adviewed = false;
				//IP2-82817 end experiment
				// card.is_template_v3 = testid > 50;
				card.is_template_v3 = false;

				var groupId = loggedInData.group || undefined;

				card.getClickAdID = function () {
					return clickid;
				};

				card.AdClicked = function ($url, returned, _openbytarget, noview) {
					var _this = this;
					try {
						var addparams,
							adparamsjson = {},
							urlParams = {};
						if (!$url) {
							return;
						}

						if ($url.indexOf("?") > -1) {
							addparams = "&";

							try {
								var uri = $url.split("?");
								urlParams = Util.Object.fromUrlParam(uri[1]);
								$url = uri[0];
								addparams = "?";
							} catch (e) {
								urlParams = {};
							}
						} else addparams = "?";

						var viewid = _this.getAdID() || Util.uniqid();

						adparamsjson.viewId = viewid;
						adparamsjson.clickId = clickid;

						if (groupId) adparamsjson.adview_groupid = groupId;

						addparams += $httpParamSerializer(Util.Object.assign(urlParams, adparamsjson));

						/* if (!getclick) clickid = Util.uniqid();
                    getclick = false; */
						if (!noview) _this.AdViewed(viewid);
						$url += addparams;
					} catch (e) {
						console.error(e);
					}

					if (returned) {
						return $url;
					}
					return false;
				};
				card.AdViewed = function (id) {
					var total_cards = $scope.filtered.length;
					if (is_pop) {
						total_cards = $scope.popcards.length;
					}

					if (adviewed || $scope.filtering) return;

					var _this = this;
					var applyLink = card.getApplyLink();
					var v = applyLink.split("&v=")[1];
					adviewed = true;
					$http({
						url: "/pixel.png",
						method: "GET",
						params: {
							adview_id: id || _this.getAdID(),
							adview_pid: _this.getId(),
							adview_page: "/credit-cards" + $location.path(),
							adview_v: v || undefined,
							approval_odds: _this.hasApprovalOds() ? _this.ApprovalOdds : $scope.my_score ? _this.getApprovalOdds($scope.my_score) : undefined,
							adview_position: !is_pop ? $scope.filtered.indexOf(_this) + 1 : $scope.popcards.indexOf(_this) + 1,
							adview_totals: total_cards,
							adview_groupid: groupId || undefined,
							adview_section: is_pop ? "poular-credit-cards" : undefined,
						},
					});

					// (IP2-38425) ctr viewed cards
					(function () {
						var vc = cookie.read("ctr_vc");

						if (!vc) {
							vc = [];
						} else {
							vc = (vc + "").split(/\s*\.\s*/);
						}

						vc.push(_this.getId());

						// Get unique non-empty ids
						vc = vc.filter(function (value, index, self) {
							return value && self.indexOf(value) === index;
						});

						// Keep track of viewed cards
						cookie.create("ctr_vc", vc.join("."));
					})();
				};
				card.AdUrlReplace = function ($url) {
					return card.AdClicked($url, true, null, true);
				};

				var curl = card.getDetailsPage(),
					curl2 = card.AdUrlReplace(card.getApplyLink(true));
				card.getDetailsPage = function (cn) {
					var view = card.getAdID();
					/*
                if (!card.action_plan &&
                    !card.as_alert &&
                    !card.ed_offer &&
                    (testid > 50 && testid < 101) &&
                    (!card.searchtool || card.isAffiliateLink($scope.ace))) {
                    return curl2.replace(/(?:([&?]viewId=)[a-f0-9]+)($|&)/, "$1" + view);
                }
                */
					if (cn == "compare-bar") {
						return curl;
					}
					var url = curl;
					return url + (url.indexOf("?") > -1 ? "&" : "?") + "viewReferrer=" + view;
				};

				var _show_min_cred = false;
				Object.defineProperty(card, "show_min_cred", {
					configurable: true,
					enumerable: true,
					get: function () {
						return _show_min_cred;
					},
					set: function (b) {
						_show_min_cred = b;
						if (!b) {
							card.min_cred_tip_hide = true;
						} else {
							card.min_cred_tip_hide = false;
						}
					},
				});

				/*
            // (IP2-64265) A/B testing of Journey Student Card
            if (card.getId() == 381) {
                // test_id 1-50
                if (test_id < 51) {
                    card.aB = false;
                    if (Array.isArray(card.xE)) {
                        var idx = card.xE.indexOf("Earn $5 per month for 12 months on Select Streaming Subscriptions when you pay on time. *Exclusions Apply");
                        if (idx > -1) {
                            card.xE.splice(idx, 1);
                        }
                    }
                    if (Array.isArray(card.ac)) {
                        var text = "Get Eno\u00ae, your Capital One\u00ae assistant, to manage your account via text, receive alerts, and shop safer online";
                        if (card.ac.length > 2) {
                            card.ac.splice(2, 0, text);
                        } else {
                            card.ac.push(text);
                        }
                    }
                }
            }
            */
			}

			var uri_to_filter_map = {},
				default_uri = $url.uri,
				refilter_timeout,
				i,
				j,
				uri;

			// initialize filters
			for (i in $filters) {
				if (["v", "defaults"].indexOf(i) > -1) {
					continue;
				}
				for (j in $filters[i]) {
					// fix regex in filter data
					if ($filters[i][j].regex != null && typeof $filters[i][j].regex == "string") {
						$filters[i][j].regex = new RegExp($filters[i][j].regex, "i");
					}
					// populate uri to filter map
					if ($filters[i][j].uri != null) {
						uri = $filters[i][j].uri;
						uri_to_filter_map[uri] = [{ ftr: i, val: j }];

						// IP2-75178 make secured/unsecured for all credit type
						// if (uri.match(/^(un)?secured$/)) {
						//     uri_to_filter_map[uri].unshift({ftr: "mc", val: "bd"});
						// }
					}
				}
			}

			// Loop again for filter aliases
			for (i in $filters) {
				if (["v", "defaults"].indexOf(i) > -1) {
					continue;
				}
				for (j in $filters[i]) {
					if ($filters[i][j].aliasuri == null || !angular.isArray($filters[i][j].aliasuri)) {
						continue;
					}
					angular.forEach($filters[i][j].aliasuri, function (uri) {
						angular.forEach(uri_to_filter_map[uri], function (ftr, k) {
							if (ftr.ftr != i || ftr.val == j) {
								return;
							}
							// If it's not an array, make it an array
							if (!angular.isArray(ftr.val)) {
								ftr.val = [ftr.val];
							}
							// Add aliased filter
							ftr.val.push(j);
							// Make changes to real arrray
							uri_to_filter_map[uri][k] = angular.merge({}, ftr);
						});
					});
				}
			}

			// record if mobile or not
			$scope.mobile = "mobile" in page && page.mobile === true;

			// record viewport width
			$scope.iw = $window.innerWidth;

			// my credit dropdown options
			// Replace with new one
			// $scope.mc_opts = [
			//     ["Excellent \u2013 Above 749", "ex"],
			//     ["Good \u2013 700-749", "gd"],
			//     ["Fair \u2013 640-699", "fr"],
			//     ["Bad \u2013 Below 640", "bd"],
			//     ["No Credit/Limited History", "nc"]
			// ];
			$scope.mc_opts = [
				["Excellent Credit", "ex"],
				["Good Credit", "gd"],
				["Fair Credit", "fr"],
				["Bad Credit", "bd"],
				["No Credit/Limited History", "nc"],
			];

			function has_approval_odds() {
				return "ao" in page && page.ao.length;
			}
			$scope.has_approval_odds = function () {
				return has_approval_odds();
			};

			if (has_approval_odds()) {
				$scope.mc_opts = [
					["Good", "gd"],
					["Fair", "fr"],
				];
				var c = 0;
				var vge = 0;
				for (i = 0; i < page.ao.length; i++) {
					if (/^((Very )?Good|Excellent)$/.test(page.ao[i][1])) {
						c++;
					}
					if (/^(Very Good|Excellent)$/.test(page.ao[i][1])) {
						vge++;
					}
				}
				// If the user has at least 5 cards cards with 'Good or above' (i.e. Excellent OR Very Good OR Good)
				// approval odds then hide the "Low" filter.
				if (c < 5) {
					$scope.mc_opts.push(["Low", "bd"]);
				}
				// If the user has NO cards cards with 'Very Good or above' (i.e. Excellent OR Very Good) approval odds
				// then hide the "Very Good" filter.
				if (vge) {
					$scope.mc_opts.splice(0, 0, ["Very Good", "ex"]);
				}
			}

			// logged in user
			$scope.isSessionActive = isSessionActive;
			if (isSessionActive && loggedInData.standing != null && loggedInData.score != null) {
				$scope.my_standing = loggedInData.standing;
				$scope.my_score = loggedInData.score;
				/*
            if (has_approval_odds()) {
            } else {
                $scope.mc_opts.push(["My Credit Score: " + loggedInData.score, "lg"]);
            }
            */
				$scope.hasCreditStanding = (page.ao && page.ao.length) > 0;
				$scope.group_id = loggedInData.group;
			}

			if (($scope.my_score && !standingInvalid) || thinfile) {
				var rgx = /(excellent|good|fair|bad|no)\-credit/,
					urij = $location.path().replace(/^\//, "").replace(/\/$/, ""), // Remove slashes
					len = urij.length;
				if (rgx.test(urij)) {
					// Remove the credit standing from the URI
					urij = urij.replace(rgx, "");
					// Remove dashes
					urij = urij.replace(/^-+/, "").replace(/-+$/, "").replace(/-+/g, "-");
					// If it changes
					if (len != urij.length) {
						window.location.href = "/credit-cards/" + (urij == "" ? "" : urij + "/");
					}
					return;
				}
			}
			if ("ao_mc_override" in page) {
				$scope.my_standing = page.ao_mc_override;
				$scope.my_score = 4;
			}

			// (IP2-58390) Auth Cards Eligible - whether the user is eligible to see apply now button for cards with lO=Y
			$scope.ace = false;
			if ("ace" in page) {
				$scope.ace = true;
			}

			// change tabs if user is logged with a standing
			if ($scope.hasCreditStanding) {
				$scope.cardsForMe = "/home/cards-for-me";
				if (document.querySelector("nav.tab-navbar")) {
					(function () {
						var tabs = document.querySelector("nav.tab-navbar");
						tabs.innerHTML = '<a class="tab" href="/home/cards-for-me/"><span>Cards for Me</span></a>' + tabs.innerHTML;
						var advisor = tabs.querySelector('a[href="/credit-card-calculator"]');
						if (advisor) tabs.removeChild(advisor);
					})();
				}
			}

			/**  === Experiment for Credit Overlay (IP2-76401) ===
       1) new design w/ anchored filters & no overlay (test IDs 1->22)
       2) new design w/ anchored filters & version 1 of overlay (test IDs 23->44)
       3) new design w/ anchored filters & version 2 of overlay (test IDs 45->66)
       4) old design w/ no overlay (test IDs 67->78)
       5) old design w/ version 1 of overlay (test IDs 79->89)
       6) old design w/ version 2 of overlay (test IDs 90->100)
       **/

			$scope.filters = angular.merge({}, $filters.defaults, page.filters != null ? page.filters : {}, typeof $scope.my_standing != "undefined" ? { mc: "lg" } : {});

			/* end of experiment */

			// IP2-75178 for location filter
			$scope.loc_error = false;
			$scope.$on("$autocomplete:listdisplay", function ($event, display) {
				if (display) {
					$scope.loc_error = false;
				} else {
					$scope.loc_error = true;
				}
				var _ac_container = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-list");
				if (_ac_container.length) {
					_ac_container[0].scrollTop = 0;
				}
			});
			$scope.filters.loc_input = "";
			if ($scope.filters.loc) {
				$scope.filters.loc_input = $scope.filters.loc;
			}
			// eof IP2-75178 for location filter

			// add institution data to filter map
			for (i = 0; i < $scope.filters.inst.length; i++) {
				j = $scope.filters.inst[i];
				// IP2-42758: No results shows for store card on activation network filter
				if (["american-express", "discover"].indexOf(j.uri) > -1) {
					continue;
				}
				if (j.uri in uri_to_filter_map) {
					uri_to_filter_map[j.uri].push({ ftr: "inst", val: j.uid });
				} else {
					uri_to_filter_map[j.uri] = [{ ftr: "inst", val: j.uid }];
				}
			}

			// variables pertaining to filtering credit card data
			$scope.filtered = [];
			$scope.banks = [];
			var def_crosslinks = {
				is_city_search: false,
				is_state_search: false,
				noindex: true,
				cities: [],
				states: [],
			};
			$scope.cross_links = angular.merge({}, def_crosslinks);
			$scope.filtered_limit = 10;
			$scope.filtered_begin = 0;
			$scope.filtered_page_total = page["total_pages"];
			$scope.filtered_cards_total = page["total_cards"];
			$scope.filtered_page = page["current_page"];
			$scope.popcards = [];
			$scope.popheadline = "";
			$scope.popsubheadline = "";
			$scope.test_template = "def";

			$scope.isM2 = function () {
				// NOT 1-25 and 51-75
				//return !((testid > 0 && testid < 26) || (testid > 50 && testid < 76));
				return true; // This experiment won so this is on all the time.
			};
			$scope.isM3 = function () {
				// 50-100
				//return testid > 50;
				return true; // This experiment won so this is on all the time.
			};

			if ("filters_tags" in page) {
				$scope.total_filters = page["filters_tags"].length;
			}

			// regular rate
			$scope.regmin = 17;
			if ("min_reg_rate" in page) {
				$scope.regmin = page["min_reg_rate"] + 0.0;
			}

			// do not fade in initially
			$scope.inview_fast = true;

			// variable to determine if the refilter() was ran at least once
			$scope.filtered_once = false;

			// variable to determine if sidebar is open
			$scope.more_filters = false;

			// important functions to determine credit
			function credit_standing_filter_value(credit_standing) {
				switch (credit_standing) {
					case "Excellent":
						return "ex";
					case "Good":
						return "gd";
					case "Fair":
						return "fr";
					case "Bad":
						return "bd";
					case "Limited":
						return "nc";
				}
				return "ex";
			}
			$scope.get_credit_standing = function () {
				var d = null;
				if (thinfile) {
					return "nc";
				}
				if ("filters" in this && "mc" in this.filters && this.filters.mc != "lg") {
					return this.filters.mc || d;
				}
				if (typeof this.my_standing != "undefined" && this.filters.mc == "lg") {
					return credit_standing_filter_value(this.my_standing || "Limited");
				}
				return d;
			};
			$scope.is_credit_standing = function (query) {
				var ctype = this.get_credit_standing();
				return query == ctype || (query == "ex" && ctype == null);
			};
			$scope.badcredit = function () {
				return this.is_credit_standing("bd");
			};

			$scope.uri_is_secured_or_unsecured = function () {
				return /^(un)?secured$/.test($url.uri);
			};
			$scope.sidebar_condensed = function () {
				// IP2-75178 condensed only for bad credit type
				// return this.badcredit() || this.uri_is_secured_or_unsecured();
				return this.badcredit();
			};

			Object.defineProperty($scope, "card_list_status", {
				get: function () {
					var text = "";
					var filtered = $scope.filtered || [];
					text += filtered.length + " card" + (filtered.length != 1 ? "s" : "") + " showing";
					if (window.innerWidth > 767) text += " Page " + $scope.filtered_page + " of " + $scope.filtered_page_total;
					return text;
				},
				configurable: true,
				enumerable: true,
			});

			// pre-calculation of variables needed in per-card filter checks
			function prepare_checkbox_filter_state_variables() {
				$scope.filters.inst_pristine = all_true($scope.filters.inst) && $scope.filters.inst_o;
				$scope.filters.rw_all_true = all_true($scope.filters.rw);
				$scope.filters.nw_all_true = all_true($scope.filters.nw);
				$scope.filters.bt_all_true = all_true($scope.filters.bt);
				// $scope.filters.emv_all_true = all_true($scope.filters.emv);
			}

			// function to determine the issuer name when only "other issuer" is selected
			// look for checked, invisible institutions
			function get_other_issuer(filters) {
				if (filters.inst_pristine) {
					return null;
				}
				var i,
					inst,
					checks = 0;
				for (i = 0; i < filters.inst.length; i++) {
					if (filters.inst[i].checked) {
						checks++;
					}
				}
				if (checks > 1) {
					return null;
				}
				for (i = 0; i < filters.inst.length; i++) {
					inst = filters.inst[i];
					if (inst.checked && "invisible" in inst && inst.invisible) {
						return inst.value;
					}
				}
				return null;
			}

			prepare_checkbox_filter_state_variables();

			// last-second filter adjustment
			$scope.filters.mc = $scope.get_credit_standing();
			$scope.credit_filter_v2 = false;

			/* end the experiment : IP2-77749
            if(!$scope.filters.mc && ( (testid > 22 && testid < 67) || (testid > 78) ) ){
                if((testid > 44 && testid < 67) || testid > 89){
                    $scope.credit_filter_v2 = true;
                }
                $scope.has_no_credit_filter = true;
                angular.element().cssSelect('body').addClass('popup-credit');
                $timeout(function(){
                    document.querySelector('.cp-heading').focus();
                },200);
            }
            if(!$scope.filters.mc){
                var has_expert_hash = window.location.hash.indexOf("#expert=") === 0;
                if(!has_expert_hash){
                    $stService.showCreditPopup(true);
                }
            }
        */
			if ($scope.filters.mc && $scope.isSessionActive) {
				var mc_index = $scope.mc_opts.findIndex(function (mc) {
					return mc[1] === $scope.filters.mc;
				});
				if (mc_index > -1) $scope.selected_credit_text = $scope.mc_opts[mc_index][0];
				$scope.mc_opts = $scope.mc_opts.filter(function (mc) {
					return mc[1] === $scope.filters.mc;
				});
			}
			(function () {
				// initialize compare cards bar saved data
				var stack = [],
					exp = 15 * 24 * 60 * 60 * 1000,
					saved;

				var gr = pitLS.group();

				var compare_bar_loaded = false;

				function SetStorageKey(name, value) {
					pitLS.group("src-prd");
					pitLS.set(name, value);
					pitLS.group(gr);
				}

				function LoadCompareBar(callback) {
					require(["cards-compare"], function () {
						var $compare = $injector.get("$comparedFactory");

						if (!compare_bar_loaded) {
							$compare.when("added", function (item) {
								stack.push(item.getId() + "c");

								pitLS.group("src-prd");
								var skp = pitLS.get("skipped_Card") || [];
								pitLS.group(gr);
								var idx = skp.indexOf(item.getId() + "c");
								if (skp && idx > -1) {
									skp.splice(idx, 1);
									SetStorageKey("skipped_Card", skp);
								}
								SetStorageKey("saved_Card", stack);
							});
							$compare.when("removed", function (item) {
								var id = item.getId() + "c";
								var idx = stack.indexOf(id);

								pitLS.group("src-prd");
								var skipped = pitLS.get("skipped_Card") || [];
								pitLS.group(gr);

								if (idx > -1) {
									stack.splice(idx, 1);
								}
								SetStorageKey("saved_Card", stack);
								if (skipped.indexOf(idx) < 0) {
									skipped.push(id);
									SetStorageKey("skipped_Card", skipped);
								}
								angular.forEach($scope.filtered, function (card) {
									if (card.getId() + "c" == id) {
										card.savedForCompare = false;
										return false;
									}
								});
							});
							$compare.when("reset", function () {
								SetStorageKey("saved_Card", []);
								SetStorageKey("skipped_Card", []);
							});
						}
						compare_bar_loaded = true;

						callback($compare);
					});
				}

				$scope.compareInit = function (card) {
					var arr = stack.length > 0 ? stack : saved;
					if (arr.indexOf(card.getId() + "c") > -1) {
						card.savedForCompare = true;
					} else {
						card.savedForCompare = false;
					}
				};

				$scope.compareSet = function (card) {
					LoadCompareBar(function ($compare) {
						var stackc = $compare.getStack();
						if (stackc.indexOf(card.getId()) < 0 && stackc.length == 7) {
							card.savedForCompare = false;
							setTimeout(function () {
								window.alert("You can select a maximum of 7 cards");
							});
						} else {
							$compare.switchItem(card);
						}
					});
				};

				pitLS.group("src-prd");
				if (!pitLS.getExpiration("saved_Card") || !pitLS.get("saved_Card")) {
					pitLS.expireKey("saved_Card", exp);
				}
				saved = pitLS.get("saved_Card") || [];
				pitLS.group(gr);
				if (saved.length > 0) {
					$http({
						url: "/ajax.php?action=Products.GetData&pid=" + saved.join(","),
					}).then(function (response) {
						LoadCompareBar(function ($compare) {
							var dt = response.data;

							if (!angular.isArray(dt)) {
								dt = [dt];
							}

							angular.forEach(dt, function (card) {
								try {
									$compare.switchItem(card);
								} catch (e) {
									console.error(e);
								}
							});
						});
					});
				}
			})();

			// the number of milliseconds to fade the element in after it has entered the viewport
			$scope.inview_debounce = 75;
			if ($window.innerWidth < 881) {
				$scope.inview_debounce = 20;
			}

			(function () {
				var cards = [],
					popcards = [],
					banks = [],
					cross_links = angular.merge({}, def_crosslinks),
					card,
					i;
				for (i = 0; i < page["initial_cards"].length; i++) {
					card = new CreditCard(page["initial_cards"][i]);
					//@ts-ignore
					card.searchtool = true;
					//@ts-ignore
					card.noforeignfee = false;
					if ($url.uri == "no-foreign-transaction-fee" || $location.$$path == "/no-foreign-transaction-fee/") {
						//@ts-ignore
						card.noforeignfee = true;
						if ($location.$$search && $location.$$search.v && $location.$$search.v == "1") {
							//@ts-ignore
							card.isForeignV1 = true;
						} else if ($location.$$search && $location.$$search.v && $location.$$search.v == "2") {
							//@ts-ignore
							card.isForeignV2 = true;
						}
					}
					// vars the cards need in the card template
					//@ts-ignore
					card.visible = false;
					//@ts-ignore
					card.details = false;
					if (i == 0) {
						if ("firstcard" in page && page["firstcard"]) {
							//@ts-ignore
							card.details = true;
						}
						if ("firstcard.20" in page && page["firstcard.20"]) {
							if (testid > 0 && testid < 21) {
								//@ts-ignore
								card.details = true;
							}
						}
					}
					// append voting data
					if (card.aM in page.votes) {
						card.vT = page.votes[card.aM][0];
						card.rG = page.votes[card.aM][1];
					}
					if (i == 0) {
						$scope.test_template = card.getTestTemplate($scope.filters);
					}
					cardAdPrepare(card);
					// take care of approval odds
					if (has_approval_odds()) {
						for (j = 0; j < page.ao.length; j++) {
							if (card.aM == page.ao[j][0]) {
								//@ts-ignore
								card.ApprovalOdds = page.ao[j][1];
								break;
							}
						}
					}
					cards.push(card);
				}
				if (page["banks"] && page["banks"].length) {
					banks = page["banks"];
				}
				if (page["cross_links"]) {
					cross_links = page["cross_links"];
				}
				if (page["initial_popcards"] && page["initial_popcards"].length) {
					for (i = 0; i < page["initial_popcards"].length; i++) {
						card = new CreditCard(page["initial_popcards"][i]);
						//@ts-ignore
						card.searchtool = true;
						//@ts-ignore
						card.noforeignfee = false;
						if ($url.uri == "no-foreign-transaction-fee" || $location.$$path == "/no-foreign-transaction-fee/") {
							//@ts-ignore
							card.noforeignfee = true;
							if ($location.$$search && $location.$$search.v && $location.$$search.v == "1") {
								//@ts-ignore
								card.isForeignV1 = true;
							} else if ($location.$$search && $location.$$search.v && $location.$$search.v == "2") {
								//@ts-ignore
								card.isForeignV2 = true;
							}
						}
						// vars the cards need in the card template
						//@ts-ignore
						card.visible = false;
						//@ts-ignore
						card.details = false;
						if (i == 0) {
							if ("firstcard" in page && page["firstcard"]) {
								//@ts-ignore
								card.details = true;
							}
							if ("firstcard.20" in page && page["firstcard.20"]) {
								if (testid > 0 && testid < 21) {
									//@ts-ignore
									card.details = true;
								}
							}
						}
						// append voting data
						if (card.aM in page.votes) {
							card.vT = page.votes[card.aM][0];
							card.rG = page.votes[card.aM][1];
						}
						if (i == 0) {
							$scope.test_template = card.getTestTemplate($scope.filters);
						}
						cardAdPrepare(card, true);
						// take care of approval odds
						if (has_approval_odds()) {
							for (j = 0; j < page.ao.length; j++) {
								if (card.aM == page.ao[j][0]) {
									//@ts-ignore
									card.ApprovalOdds = page.ao[j][1];
									break;
								}
							}
						}
						popcards.push(card);
					}
				}
				$timeout(function () {
					$scope.filtered = cards;
					$scope.banks = banks;
					$scope.cross_links = cross_links;
					$scope.popcards = popcards;
					if (popcards.length) {
						if (page["popheadline"]) $scope.popheadline = page["popheadline"];
						if (page["popsubheadline"]) $scope.popsubheadline = page["popsubheadline"];
					}
					$scope.initialized_cards = true;
				});
			})();

			angular.extend($scope, {
				// expands / collapses the "More Filters" section
				more_filters_toggle: function (evt) {
					this.more_filters = !this.more_filters;
					evt.preventDefault();

					setTimeout(function () {
						var el = document.querySelector('[data-focus-to="balance"]');
						if (el) {
							//@ts-ignore
							el.focus();
						}
					}, 100);
				},

				// filters tags
				filters_tags: page.filters_tags || [],
				remove_filter_tag: function (ftr, val) {
					// make this an array because there can be additional filters to remove depending on the filter being removed
					ftr = [ftr];

					// if user has selected "Student" + "No Credit", and then removing any of these tags should remove the other tag as well
					// if (($scope.filters.iam == "cs" && $scope.filters.mc == "nc") && (ftr == "iam" || ftr == "mc")) {
					//     ftr.push(ftr == "iam" ? "mc" : "iam");
					// }

					// IP2-75178 dont remove secured/unsecured card
					// if user is removing "Bad Credit" tag while "Secured" or "Unsecured" tag is selected, remove it also
					// if ($scope.badcredit() && ftr == "mc" && (!$scope.filters.iws.sc || !$scope.filters.iws.us)) {
					//     ftr.push("iws");
					// }

					var i, j, ftri;

					for (i = 0; i < ftr.length; i++) {
						ftri = ftr[i];

						// remove the tag
						j = $scope.filters_tags.length;
						while (j--) {
							if (ftri == $scope.filters_tags[j].ftr) {
								$scope.filters_tags.splice(j, 1);
							}
						}

						if (ftri in $scope.filters) {
							if (!(ftri in $filters.defaults) || $filters.defaults[ftri] == null) {
								$scope.filters[ftri] = null;
							} else {
								if (typeof $scope.filters[ftri] != "string" && val in $scope.filters[ftri] && typeof $filters.defaults[ftri] != "string" && val in $filters.defaults[ftri]) {
									$scope.filters[ftri][val] = angular.copy($filters.defaults[ftri][val]);
								} else if (typeof $filters.defaults[ftri] == "string") {
									$scope.filters[ftri] = angular.copy($filters.defaults[ftri]);
								} else {
									$scope.filters[ftri] = angular.merge({}, $filters.defaults[ftri]);
								}
							}
							// restore rewards checks when closed
							if (ftri == "iw" && val == "rw") {
								$scope.filters.rw = angular.merge({}, $filters.defaults.rw);
							}
							if (ftri == "inst") {
								$scope.filters.inst_o = true;
							}
						}
					}
					if (ftr == "iam" && !val && $scope.filters.chcrd && $scope.filters.chcrd == "y") {
						$scope.filters.iam = null;
					}

					if ($scope.filters.mc == null && $scope.hasCreditStanding) {
						$scope.mycredit_changing = true;
					}
					// IP2-75178 remove loc input as well
					$scope.filtered_page = 1;
					$url.entry = "user";
					refresh_page_on_ui_event();
					if (ftr == "loc") {
						$scope.filters.loc_input = "";
						setTimeout(function () {
							window.history.pushState({}, document.title, window.location.pathname);
						});
						window.location.hash = "";
						refilter();
					}
				},
				reset_filters: function () {
					// Get old approval odds
					var mc = null;
					if (has_approval_odds() || $scope.my_standing) {
						mc = $scope.filters.mc;
						if ($scope.my_standing) {
							mc = credit_standing_filter_value($scope.my_standing);
						}
					} else if (thinfile) {
						mc = "nc";
					}
					var filters = {};
					angular.merge(filters, $filters.defaults);
					if (mc !== null) {
						filters.mc = mc;
					}
					$scope.filters = filters;
					$scope.filtered_page = 1;
					$url.entry = "user";
					$scope.$applyAsync(function () {
						refresh_page_on_ui_event();
						refilter();
					});
				},

				reset_more_filters: function () {
					// Get old approval odds
					var mc = null;
					var iw = null;
					var iws = null;
					var iam = null;
					var loc = null;
					if ($scope.filters.iam) {
						iam = $scope.filters.iam;
					}
					if ($scope.filters.mc) {
						mc = $scope.filters.mc;
					}
					if ($scope.filters.mc && $scope.filters.mc == "bd" && $scope.filters.iws) {
						iws = $scope.filters.iws;
					} else if ($scope.filters.iw) {
						iw = $scope.filters.iw;
					}
					if (!$scope.cc_plan_text_name) {
						if ($scope.filters.loc_input) {
							$scope.filters.loc_input = "";
						}
						loc = $scope.filters.loc;
					}
					var filters = {};
					angular.merge(filters, $filters.defaults);
					if (iam !== null) {
						filters.iam = iam;
					}
					if (mc !== null) {
						filters.mc = mc;
					}
					if (iw !== null) {
						filters.iw = iw;
					}
					if (loc !== null) {
						filters.loc = loc;
					}
					if (iws !== null) {
						filters.iws = iws;
					}
					$scope.filters = filters;
					$scope.filtered_page = 1;
					$url.entry = "user";
					$scope.$applyAsync(function () {
						refresh_page_on_ui_event();
						refilter();
					});
				},

				// regular rate slider variables
				reg_disabled_width: function () {
					$scope.regmin = $scope.filters.reg > 0 ? 0 : $scope.regmin;
					return ($scope.regmin / 30) * 100 + "%";
				},

				// save old network when switching between bad and non-bad credit
				nw_old: {},

				// contents of sort dropdown
				sort_opts: [
					["Featured", "ftr"],
					["Most Popular", "pop"],
					["Editor\u2019s Picks", "ep"],
					["User Rating", "rtg"],
					["Rates \u2013 0% on Purchases", "pch"],
					["Rates \u2013 0% on Transfers", "bt"],
					["Rates \u2013 Regular Rate", "reg"],
					["Rewards \u2013 Initial Bonus", "init"],
					["Rewards \u2013 Base Earn", "base"],
					["Rewards \u2013 Max Earn", "max"],
				],

				// changing "My Credit" dropdown of logged in user
				mycredit_change: function () {
					$scope.mycredit_changing = true;
					/** @type {HTMLButtonElement} */
					var bt = document.querySelector('[data-focus-to="filter-cards-drp"] .ng-dropdown-selected-ang');
					if (bt) {
						bt.focus();
						setTimeout(function () {
							bt.focus();
						});
					}
				},

				// select only specific institution in instutitions filter
				only_company: function (uid) {
					for (var i in $scope.filters.inst) {
						$scope.filters.inst[i].checked = $scope.filters.inst[i].uid == uid;
					}
					$scope.filters.inst_o = uid == "o";
					$scope.change_filter("inst", uid);
				},

				// select all companies
				all_companies: function () {
					for (var i in $scope.filters.inst) {
						$scope.filters.inst[i].checked = true;
					}
					$scope.filters.inst_o = true;
					$scope.change_filter("inst");
				},

				showCardImage: function (card, inview) {
					if (inview) {
						$timeout(function () {
							card.visible = true;
						}, 10);
					}
				},

				showImageInview: function (img, src) {
					if (/silhouette-[0-9]+\.png/.test(src) !== false || img.src == src) {
						return;
					}
					img.src = src;
				},

				toggleDetails: function (_evt, card) {
					if (card) {
						card.details = !card.details;
						if (!card.details) {
							card.details_closed = true;
							$timeout(function () {
								card.details_closed = false;
							}, 300);
						}
						/* var $cie = $(evt.element).parents('.cards').find('.card-info-extras');
                    if ($cie) {
                        $cie.addClass("force-redraw");
                        $timeout(function () {
                            $cie.removeClass("force-redraw");
                        }, 0);
                    } */
						$window.scrollTo(0, $window.pageYOffset - 1);
					}
				},

				toggleEditorsTake: function (_evt, card) {
					if (card) {
						card.details_editors = !card.details_editors;
						if (!card.details_editors) {
							card.details_editors_closed = true;
							$timeout(function () {
								card.details_editors_closed = false;
							}, 300);
						}
						$window.scrollTo(0, $window.pageYOffset - 1);
					}
				},

				openDetails: function (_evt, card) {
					card.details = true;
					$window.scrollTo(0, $window.pageYOffset - 1);
					$window.scrollTo(0, $window.pageYOffset + 1);
				},

				toggleDetailsBad: function (evt) {
					angular.element(evt.target.parentNode.parentNode).toggleClass("more");
				},

				clearPageFilters: function () {
					page.filters = null;
					$scope.filters = angular.merge({}, $filters.defaults);
				},
			});

			function restore_filters_from_query(query) {
				var ftr, val, i;

				// uncheck everything
				for (ftr in query) {
					switch (ftr) {
						case "rw":
						case "nw":
						case "bt":
							// case "emv":
							for (i in $scope.filters[ftr]) {
								$scope.filters[ftr][i] = false;
							}
							break;
						case "iw":
							// IP2-75178 make 0% purchase and 0% balance transfer false for bad credit
							if (query.mc == "bd") {
								$scope.filters.iw.pch = false;
								$scope.filters.iw.bt = false;
							}
							break;
						case "iws":
							// IP2-75178 make secured / unsecured as stand alone filter
							$scope.filters.iws.sc = false;
							$scope.filters.iws.us = false;
							break;
						case "inst":
							$scope.filters.inst_o = false;
							for (i = 0; i < $scope.filters.inst.length; i++) {
								$scope.filters.inst[i].checked = false;
							}
							break;
					}
				}

				// activate filters in query
				for (ftr in query) {
					val = query[ftr];
					if (ftr == "inst") {
						$scope.filters.inst_o = val.indexOf("o") > -1;
						for (i = 0; i < $scope.filters.inst.length; i++) {
							$scope.filters.inst[i].checked = val.indexOf($scope.filters.inst[i].uid + "") > -1;
						}
					} else if (["iam", "mc", "pic", "cha", "ft", "reg", "emv"].indexOf(ftr) > -1) {
						if (ftr == "reg") {
							val[0] = parseFloat(val[0]);
							if (val[0] > 30) {
								val[0] = 30;
							}
						}
						$scope.filters[ftr] = val[0];
					} else if (ftr != "p") {
						// check selected
						for (i = 0; i < val.length; i++) {
							if (ftr == "bt" && val[i] != "n") {
								$scope.filters[ftr][ftr + val[i]] = true;
							} else if (ftr in $scope.filters) {
								$scope.filters[ftr][val[i]] = true;
							}
						}
					}
				}

				if (query["srt"] != null) {
					$scope.filters.srt = query["srt"][0];
				}
				if (query["p"] != null) {
					$scope.filters.p = parseInt(query["p"]);
					if (!isNaN($scope.filters.p)) {
						$scope.filters.p = 1;
					}
				}
			}

			function restore_filters_from_uri(uri) {
				var uris = [],
					regex,
					found,
					ftrs,
					ftr,
					i,
					j,
					k;

				// try to see if the uri is in customUri
				/*
            for (i in customUri) {
                if (i == uri) {
                    uri = "";
                    if ("uri" in customUri[i]) {
                        uris = customUri[i].uri;
                    } else if (i.indexOf("-") == -1) {
                        uris.push(i);
                    }
                }
            }
            */

				// loop through the dictionary and extract possible uris from the left of the uri
				while (uri != "") {
					found = false;
					for (i in uri_to_filter_map) {
						regex = new RegExp("^" + i + "-?");
						if (regex.test(uri)) {
							uris.push(i);
							uri = uri.replace(regex, "");
							found = true;
							break;
						}
					}
					if (!found) {
						break;
					}
				}

				if (uri == "compare") {
					uri = "";
					uris = [];
				}

				// custom uri was not found
				if (uri != "") {
					return;
				}

				if ($url.entry == "system") {
					$scope.filters = angular.merge({}, $filters.defaults, { iam: "gc" });
				}

				// uncheck everything
				for (i = 0; i < uris.length; i++) {
					if (!(uris[i] in uri_to_filter_map)) {
						continue;
					}
					ftrs = uri_to_filter_map[uris[i]];
					for (j = 0; j < ftrs.length; j++) {
						ftr = ftrs[j].ftr;
						switch (ftr) {
							case "rw":
							case "nw":
							case "bt":
								// case "emv":
								for (k in $scope.filters[ftr]) {
									$scope.filters[ftr][k] = false;
								}
								break;
							case "iw":
								// IP2-75178 make 0% purchase and 0% balance transfer false for bad credit
								if (uris.indexOf("bad-credit") > -1) {
									$scope.filters.iw.pch = false;
									$scope.filters.iw.bt = false;
								}
								break;
							case "iws":
								// IP2-75178 make secured / unsecured as stand alone filter
								$scope.filters.iws.us = false;
								$scope.filters.iws.sc = false;
								break;
							case "inst":
								// if discover/amex is found in the uri, restrict it to a network only check
								if (["discover", "american-express"].indexOf(uris[i]) > -1) {
									continue;
								}
								$scope.filters.inst_o = false;
								for (k in $scope.filters[ftr]) {
									$scope.filters[ftr][k].checked = false;
								}
								break;
							default:
								$scope.filters[ftr] = ftrs[j].val;
								break;
						}
					}
				}

				if (uris.length == 1 && ["american-express"].indexOf(uris[0]) > -1) {
					$scope.filters.inst_o = false;
				}

				// second loop to apply the filters
				for (i = 0; i < uris.length; i++) {
					if (!(uris[i] in uri_to_filter_map)) {
						continue;
					}
					ftrs = uri_to_filter_map[uris[i]];
					for (j = 0; j < ftrs.length; j++) {
						ftr = ftrs[j].ftr;
						var val = ftrs[j].val;
						if (!(ftr in $scope.filters)) {
							$scope.filters[ftr] = null;
						}
						if (ftr == "inst") {
							// if discover/amex is found in the uri, restrict it to a network only check
							if (["discover", "american-express"].indexOf(uris[i]) > -1 && uris.length != 1) {
								continue;
							}
							for (k = 0; k < $scope.filters.inst.length; k++) {
								if ($scope.filters.inst[k].uid == val) {
									$scope.filters.inst[k].checked = true;
								}
							}
						} else if (["iam", "mc", "stcrd", "chcrd", "pic", "cha"].indexOf(ftr) > -1) {
							$scope.filters[ftr] = val;
						} else if (angular.isArray(val)) {
							angular.forEach(val, function (k) {
								$scope.filters[ftr][k] = true;
							});
						} else {
							$scope.filters[ftr][val] = true;
						}
					}
				}
			}

			var canceller = $q.defer();

			function refilter() {
				if ($scope.show_sidebar_filters) {
					$scope.delayed_filter = true;
					return;
				}

				var filters = angular.merge({}, $scope.filters);

				// last-second filter adjustment
				filters.mc = $scope.get_credit_standing();
				filters.other_issuer = get_other_issuer(filters);

				var refilter_start = function () {
					$scope.$broadcast("filter:start");

					var headers = {
							"If-Modified-Since": "Mon, 26 Jul 1997 05:00:00 GMT",
							"Cache-Control": "no-cache",
							Pragma: "no-cache",
							Accept: "application/json",
							"X-Requested-With": "XMLHttpRequest",
							"App-Id": "ccst-desktop-" + (window["v"] || 1),
						},
						url = window.location.pathname,
						qstr = window.location.search,
						hash = window.location.hash;
					if (hash.indexOf("#loc=") === 0) {
						var _loc = hash.substring(5);
						if (_loc) {
							_loc = decodeURI(_loc);
							$scope.filters.loc = _loc;
							$scope.filters.loc_input = _loc;
							if (qstr) {
								qstr += ";loc:" + _loc;
							} else {
								qstr = "?q=loc:" + _loc;
							}
						}
					}
					angular
						.element()
						.cssSelect(".feedback-url")
						.attr("href", "/feedback/?ref=" + url);
					if ($scope.cards_page_change || $scope.cards_page_change_mob) {
						headers["X-Paginating"] = true;
						headers["X-Pagination-Page"] = $scope.filtered_page;
					}
					if (isSessionActive) {
						if (loggedInData.group) {
							headers["X-Ithaca-Group-Id"] = loggedInData.group;
						}
						if (filters.mc !== null) {
							headers["X-Credit-Override"] = filters.mc;
						}
						if (has_approval_odds()) {
							var ao = ["Excellent", "Very Good", "Good"];
							if (filters.mc == "ex") {
								ao = ["Excellent", "Very Good"];
							} else if (filters.mc == "fr") {
								ao = ["Excellent", "Very Good", "Good", "Fair"];
							} else if (filters.mc == "bd") {
								ao = ["Excellent", "Very Good", "Good", "Fair", "Low"];
							}
							var aomap = [],
								i;
							for (i in page.ao) {
								if (ao.indexOf(page.ao[i][1]) > -1) {
									aomap.push(page.ao[i]);
								}
							}
							headers["X-Approval-Odds-Filter"] = angular.toJson(aomap);
						}
						var signon = cookie.read("mw_signon") || "{}";
						if (signon.length > 2 && signon.charAt(0) == "{" && signon.charAt(signon.length - 1) == "}") {
							signon = angular.fromJson(signon);
							if (angular.isObject(signon) && "inv" in signon) {
								if (signon.inv) {
									headers["X-Invalid-Standing"] = true;
								}
							}
						}
					}
					if (standingInvalid) {
						headers["X-Invalid-Standing"] = true;
					}

					if (qstr == "") {
						//qstr = "?";
					}

					// qstr += (qstr == "?" ? "" : "&") + "cb=" + new Date().getTime();

					if ($http.pendingRequests.length) {
						canceller.resolve();
						canceller = $q.defer();
					}

					let paginating = false;
					if (headers && angular.isObject(headers)) {
						if ("X-Paginating" in headers) {
							paginating = true;
						}
					}

					$http
						.get(url + qstr, {
							headers: headers,
							cache: false,
							timeout: canceller.promise,
						})
						.then(
							function (response) {
								var cards = [],
									card,
									headers = response.headers(),
									pages,
									i,
									j;
								$scope.banks = [];
								$scope.cross_links = angular.merge({}, def_crosslinks);
								var initcard = function (data, is_pop) {
									var c = new CreditCard(data);
									//@ts-ignore
									c.searchtool = true;
									//@ts-ignore
									c.noforeignfee = false;
									if ($url.uri == "no-foreign-transaction-fee" || $location.$$path == "/no-foreign-transaction-fee/") {
										//@ts-ignore
										c.noforeignfee = true;
										if ($location.$$search && $location.$$search.v && $location.$$search.v == "1") {
											//@ts-ignore
											c.isForeignV1 = true;
										} else if ($location.$$search && $location.$$search.v && $location.$$search.v == "2") {
											//@ts-ignore
											c.isForeignV2 = true;
										}
									}
									// vars the cards need in the card template
									//@ts-ignore
									c.visible = false;
									//@ts-ignore
									c.details = false;
									// append voting data
									if (c.aM in page.votes) {
										c.vT = page.votes[c.aM][0];
										c.rG = page.votes[c.aM][1];
									}
									cardAdPrepare(c, is_pop);
									// Add approval odds
									if (has_approval_odds()) {
										for (j = 0; j < page.ao.length; j++) {
											if (c.aM == page.ao[j][0]) {
												//@ts-ignore
												c.ApprovalOdds = page.ao[j][1];
												break;
											}
										}
									}
									return c;
								};

								for (i = 0; i < response.data.cards.length; i++) {
									card = initcard(response.data.cards[i]);
									if (i == 0) {
										$scope.test_template = card.getTestTemplate(filters);
									}
									cards.push(card);
								}

								$scope.after_filtering = null;

								var through_pagination_button = $scope.load_more_cards || false;
								var cards_page_change_mob = $scope.cards_page_change_mob;
								if (through_pagination_button) {
									$scope.cards_loaded_status = "Loaded " + cards.length + " more card" + (cards.length != 1 ? "s" : "");
									if (cards_page_change_mob) $scope.after_filtering = $scope.filtered.length;
								}
								$timeout(function () {
									// turn off animation
									$scope.filtering = false;
									$scope.load_more_cards = false;

									/* $scope.after_filtering = null;
                        $timeout(function(){
                            $scope.after_filtering = false;
                        },100); */

									if ("data_error" in response.data && response.data["data_error"] === true) {
										return;
									}
									$scope.initialized_cards = true;
									// set new results
									if ($scope.cards_page_change_mob) {
										$scope.filtered = $scope.filtered.concat(cards);
										$scope.filtered_limit = $scope.filtered_page_total * 10;
										$scope.cards_page_change_mob = false;
									} else {
										$scope.filtered = cards;
										$scope.filtered_limit = 10;
										$scope.cards_page_change = false;
									}

									// set new min reg rate
									$scope.regmin = response.data.regmin;
									// update pagination
									if ("x-pagination-count" in headers) {
										pages = parseInt(headers["x-pagination-count"]);
										if (!isNaN(pages)) {
											$scope.filtered_page_total = pages;
										}
									}
									if ("x-pagination-page" in headers) {
										var cp = parseInt(headers["x-pagination-page"]),
											tp = parseInt(headers["x-pagination-count"]);
										if (!isNaN(cp) && !isNaN(tp)) {
											$scope.filtered_page = cp > tp ? tp : cp;
										}
									}
									// update cards
									if ("x-pagination-cards" in headers) {
										page["total_cards"] = headers["x-pagination-cards"];
										$scope.filtered_cards_total = headers["x-pagination-cards"];
									}

									// reset popular cards
									$scope.popcards = [];
									$scope.popheadline = "";
									$scope.popsubheadline = "";

									// Delete all previous curi-qa elements
									if (!paginating) {
										angular.element().cssSelect(".box-container-picks").remove();
									}

									// update description
									var cls = document.body.className;
									if (response && response.data && response.data.curi) {
										var cu = response.data.curi;
										if ("class" in cu) {
											angular
												.element()
												.cssSelect(".intro")
												.attr("class", "intro" + cu.class);
										}
										if (!paginating && cu.hasOwnProperty("eqa") && cu.eqa) {
											// Add new curi-qa content
											angular.element().cssSelect("#qna").before(cu.eqa);
										}

										$scope.titleclass = cu.geolocation ? "geolocation" : false;
										if ("mapped" in cu && cu.mapped !== false) {
											restore_filters_from_uri(cu.mapped);
										}

										if ("bodyclass" in response.data) {
											cls = response.data["bodyclass"];
										}
										if (cu.hasOwnProperty("popcards") && cu.popcards.length) {
											var pcards = [];
											for (var i = 0; i < cu.popcards.length; i++) {
												pcards.push(initcard(cu.popcards[i], true));
											}
											$scope.popcards = pcards;
										}
										if (cu.hasOwnProperty("popheadline")) {
											$scope.popheadline = cu.popheadline;
										}
										if (cu.hasOwnProperty("popsubheadline")) {
											$scope.popsubheadline = cu.popsubheadline;
										}

										$stService.setIntro({
											top: cu.content,
											btm: cu.content2,
											title: cu.title,
											headline: cu.headline,
											filtername: cu.filtername,
										});
									} else {
										$stService.setIntro({
											title: "Credit Cards",
											top: "Compare credit card offers (some of which are from WalletHub advertisers) and quickly find the one that best fits your needs. Once you've made your choice, click \"Apply Now\" and we'll redirect you to the credit card company's secure online application.",
											btm: "",
											headline: "WalletHub experts track 1,500+ offers to help you get the right credit card.",
											filtername: "FILTER CARDS",
										});
									}

									// Hide expert-opinions and q&a even without "eqa" or custom uri
									if (!paginating) {
										angular.element().cssSelect("#expert-opinions").hide();
										angular.element().cssSelect(".comqa").hide();
									}

									// Decide whether to hide top_picks or not
									const top_picks_el = angular.element().cssSelect(".box-container-picks#editors-picks-2");
									if (top_picks_el.length) {
										angular.element().cssSelect(".jmp-item-picks").show();
									} else {
										angular.element().cssSelect(".jmp-item-picks").hide();
									}

									// Decide whether to hide research or not
									const research_el = angular.element().cssSelect(".box-container-picks#editors-picks-0");
									if (research_el.length) {
										angular.element().cssSelect(".jmp-item-research").show();
									} else {
										angular.element().cssSelect(".jmp-item-research").hide();
									}

									// update filter tags
									if (response.data.tags != null) {
										$scope.filters_tags = angular.merge({}, response.data.tags);
									}
									// update ace_reqd
									if ("ace" in response.data && response.data.ace) {
										pitLS.set("ace", true);
										$scope.ace = true;
									} else {
										$scope.ace = false;
										pitLS.set("ace", false);
									}
									if (!has_approval_odds() && !thinfile) {
										$scope.my_score = null;
									}
									if (response.data.banks && response.data.banks.length) {
										$scope.banks = response.data.banks;
									}
									if (response.data.cross_links) {
										$scope.cross_links = response.data.cross_links;
									}
									// update page class
									document.body.className = cls;
								});
								$scope.$broadcast("filter:end", response.data);
							},
							function () {
								$timeout(function () {
									// turn off animation
									$scope.filtering = false;
									$scope.load_more_cards = false;
									$scope.after_filtering = null;
									angular.forEach($(".cardhub-edu-table"), function (element, _i) {
										if (!$(element).parent().is(".cardhub-edu-table-div")) {
											$(element).wrap('<div class="cardhub-edu-table-div" />');
										}
									});
								});
							}
						);
				};

				// show loading animation
				$scope.show_loading_animation();

				// do the magic
				$timeout.cancel(refilter_timeout);
				refilter_timeout = $timeout(refilter_start, 100);

				$scope.inview_fast = false;
				$scope.filtered_once = true;
				$scope.delayed_filter = false;
			}
			$scope.getStarsClass = function (rating) {
				var stars = [],
					rate = rating,
					ft = rate,
					it = parseInt(rate),
					fract = ft - it,
					i;
				for (i = 0; i < 5; i++) {
					if (i < it || (i == it && fract > 0.87)) {
						stars.push("bf-icon-star-twotone");
					} else if (i == it && fract > 0.12 && fract < 0.38) {
						stars.push("bf-icon-star-twotone-quarter");
					} else if (i == it && fract > 0.37 && fract < 0.63) {
						stars.push("bf-icon-star-twotone-half");
					} else if (i == it && fract > 0.62 && fract < 0.88) {
						stars.push("bf-icon-star-twotone-three-quarter");
					} else {
						stars.push("bf-icon-star-twotone-empty");
					}
				}
				return stars;
			};

			$scope.show_loading_animation = function () {
				$scope.filtering = true;

				if (!$scope.__track_scroll) {
					var trackScroll = function () {
						var sc = $viewport.body.prop("scrollTop") + 55,
							ct = angular.element().cssSelect("#searchtool .cards-container"),
							ldb = angular.element().cssSelect("#searchtool .loading-box"),
							//@ts-ignore
							min = ct.offset().top,
							//@ts-ignore
							max = ct.offset().top + ct.prop("offsetHeight") - ldb.prop("offsetHeight");
						ldb.css("top", Math.min(max, Math.max(min, sc)) + "px");
					};
					angular.element(window).on("scroll", trackScroll);
					trackScroll();
					$scope.__track_scroll = true;
				}
			};

			// IP2-80856 Eliminate the ajax calls that fetches the card order every time on credit card search tool
			var rf = false;

			// (IP2-39610) If a user is (logged in) AND has (creditStanding = Excellent OR Good OR Fair OR Bad OR ThinFile)
			if (loggedInData && (["Excellent", "Good", "Fair", "Bad"].indexOf(loggedInData.standing) > -1 || thinfile)) {
				rf = true;
			}

			var qs = window.location.search;
			if (qs.includes("utm_geo=yes")) {
				rf = true;
			}

			if (qs.includes("utm_geo=yes")) {
				rf = true;
			}
			var _hash = window.location.hash;
			if (_hash.indexOf("#loc=") === 0) {
				var _loc = _hash.substring(5);
				if (_loc) {
					refilter();
				}
			}

			if (rf) {
				refilter();
			}

			// handling filters based on location object
			$scope.$on("$url:changed", function (_$event, from, to) {
				if (null === default_uri) {
					default_uri = $url.uri;
				}

				if (from == to || from === null) {
					return false;
				}

				if ("cf" in $location.search()) {
					$scope.clearPageFilters();
				}

				if (window.location.hash.length > 0) {
					// setTimeout(function(){
					//     window.history.replaceState({}, document.title, window.location.pathname);
					// });
					// window.location.hash = "";
				}

				if (Object.keys($url.filters).length > 0) {
					restore_filters_from_query($url.filters);
					refresh_page_on_ui_event("system");
					refilter();
				} else if (page["filters"] != null) {
					page.filters = null; // use the JSON only one time
					if ($scope.hasCreditStanding) {
						$url.entry = "user";
					}
					refresh_page_on_ui_event();

					//if ($scope.filtered_once) {
					refilter();
					//}

					$scope.filtered_once = true;
				} else if ($url.uri != "") {
					restore_filters_from_uri($url.uri);
					refresh_page_on_ui_event("system");

					refilter();
				} else {
					restore_filters_from_uri("");

					if ($scope.filtered_once) {
						refilter();
					}
				}

				// default back to system until $scope.change_filter is called again
				$url.entry = "system";
			});

			// IP2-75178 make secured / unsecured as stand alone filter
			$scope.loc_focus = function () {
				if (showing_loc) {
					$scope.$applyAsync(function () {
						$scope.mobLoc = true;
						showing_loc = true;
					});
				}
			};

			// called in ng-change of all filters
			// calls refresh_page_on_ui_event()
			$scope.change_filter = function (ftr, val) {
				if (showing) {
					$scope.$applyAsync(function () {
						$scope.mobIW = true;
						showing = true;
					});
				}
				if (showing_more) {
					$scope.$applyAsync(function () {
						$scope.drpMore = true;
						showing_more = true;
					});
				}
				if (showing_loc) {
					$scope.$applyAsync(function () {
						$scope.mobLoc = true;
						showing_loc = true;
					});
				}
				var restore_hdn_nw = false,
					allfalse,
					i;
				if (ftr == "iam" && $scope.filters.iam && $scope.filters.iam == "cs") {
					// Charge cards does not combine
					$scope.filters.chcrd = "n";
					// only add "no-credit" if there are no other filters
					if (
						filter_pristine("mc") &&
						filter_pristine("iw") &&
						filter_pristine("rw") &&
						filter_pristine("rw") &&
						filter_pristine("nw") &&
						filter_pristine("bt") &&
						filter_pristine("ft") &&
						filter_pristine("emv") &&
						filter_pristine("pic") &&
						filter_pristine("cha") &&
						filter_pristine("chcrd") &&
						filter_pristine("inst") &&
						filter_pristine("iws") &&
						filter_pristine("loc")
					) {
						$scope.filters.mc = "nc";
						restore_hdn_nw = true;
					}
				}
				// if bad, record amex/discover selection
				if ($scope.badcredit()) {
					if (Object.keys($scope.nw_old).length == 0) {
						$scope.nw_old = {
							am: $scope.filters.nw.am,
							di: $scope.filters.nw.di,
						};
					}
					// last click was bad
					if (ftr == "mc") {
						if (!$scope.filters.nw.vi && !$scope.filters.nw.mc) {
							$scope.filters.nw.vi = true;
						}
						// IP2-75178 make secured / unsecured as stand alone filter
						// $scope.filters.iw.sc = true;
						// $scope.filters.iw.us = true;
						// IP2-75178 make 0% purchase and 0% balance transfer false for bad credit
						$scope.filters.iw.pch = false;
						$scope.filters.iw.bt = false;
					}
				} else if (ftr == "mc") {
					restore_hdn_nw = true;
				}
				// for these filters, if nothing is selected in the group, select at least one
				if ((["rw", "nw"].indexOf(ftr) > -1 && all_false($scope.filters[ftr])) || (ftr == "nw" && $scope.badcredit() && !$scope.filters.nw.vi && !$scope.filters.nw.mc)) {
					if (ftr == "rw") {
						val = val != "cb" ? "cb" : "gas";
					}
					if (ftr == "nw") {
						val = val != "vi" ? "vi" : "mc";
					}
					// if (ftr == "emv") {
					//     val = val != "n" ? "n" : "pn";
					// }
					$scope.filters[ftr][val] = true;
				}
				// IP2-75178 make secured / unsecured as stand alone filter
				// if (ftr == "iw") {
				if (ftr == "iws") {
					// if (!($scope.filters.iw.sc && $scope.filters.iw.us)) {
					//     $scope.filters.iw[val == "sc" ? "us" : "sc"] = true;
					// }
					// if nothing is selected in the group, select at least one, isolated because the control shares "iw" name with others
					if (!($scope.filters.iws.sc && $scope.filters.iws.us)) {
						$scope.filters.iws[val == "sc" ? "us" : "sc"] = true;
					}
				}
				if (ftr == "iwr") {
					$scope.filters.iw.pch = false;
					$scope.filters.iw.bt = false;
					$scope.filters.iw.reg = false;
					$scope.filters.iw.af = false;
					$scope.filters.iw.rw = false;
					if (val in $scope.filters.iw) {
						$scope.filters.iw[val] = true;
					}
				}
				// if no institution is selected, select at least one
				if (ftr == "inst") {
					allfalse = true;
					for (i = 0; i < $scope.filters.inst.length; i++) {
						if ($scope.filters.inst[i].checked) {
							allfalse = false;
							break;
						}
					}
					if (allfalse && !$scope.filters.inst_o) {
						val = val != 13000208 ? 13000208 : 13000450;
						// check only one
						for (i = 0; i < $scope.filters.inst.length; i++) {
							$scope.filters.inst[i].checked = $scope.filters.inst[i].uid == val;
						}
					}
				}
				// Charge Cards can only be combined with business or general consumer
				if ($scope.filters.chcrd == "y") {
					if ((ftr != "iam" && ftr != "chcrd") || (ftr == "iam" && val == "cs")) {
						$scope.filters.chcrd = "n";
					}
					if (ftr == "chcrd" && !all_true($scope.filters.nw)) {
						$scope.filters.nw.am = true;
						$scope.filters.nw.vi = true;
						$scope.filters.nw.mc = true;
						$scope.filters.nw.di = true;
					}
				}
				if (ftr == "chcrd") {
					if ($scope.filters.iam == "cs") {
						filter_make_pristine("iam");
					}
					var pristine = ["iw", "rw", "nw", "bt", "ft", "emv", "ft", "pic", "cha", "inst", "inst_o", "stcrd", "iws", "loc"];
					if (typeof $scope.my_standing === "undefined") {
						pristine.unshift("mc");
					}
					filters_make_pristine.apply($scope, pristine);
				}
				if (ftr != "p") {
					$scope.filtered_page = 1;
				}
				// restore hidden network selection
				if (restore_hdn_nw) {
					angular.extend($scope.filters.nw, $scope.nw_old);
					$scope.nw_old = {};
				}
				if ((!$scope.filters.chcrd || $scope.filters.chcrd != "y") && !$scope.filters.iam) {
					$scope.filters.iam = "gc";
				}
				// this will change uri
				$url.entry = "user";
				refresh_page_on_ui_event();
			};

			$scope.uncheck_no_balance_transfer = function (evt) {
				window.alert("You can not uncheck 'None', because everyone enjoys a card without a balance transfer fee.");
				evt.preventDefault();
			};

			function refresh_page_on_ui_event(entry) {
				var query = [],
					qstr = $location.search(),
					lpath = $location.path(),
					uris = [],
					tags = [],
					val,
					i,
					j,
					doquery = false;

				if (typeof entry != "undefined" && $url.entry != entry) {
					return;
				}

				prepare_checkbox_filter_state_variables();

				// fix more filters
				// if (!$scope.filters.bt_all_true || $scope.filters.ft == "y" || !$scope.filters.emv_all_true || $scope.filters.pic == "y" || $scope.filters.cha == "y" || !$scope.filters.inst_pristine || $scope.filters.stcrd == "y" || $scope.filters.chcrd == "y" || $scope.filters.emvn != "n") {
				if (!$scope.filters.bt_all_true || $scope.filters.ft == "y" || $scope.filters.pic == "y" || $scope.filters.cha == "y" || !$scope.filters.inst_pristine || $scope.filters.stcrd == "y" || $scope.filters.chcrd == "y" || $scope.filters.emv != "n") {
					$scope.more_filters = $url.entry == "user";
				}

				val = $scope.filters.iam;
				if ((val && val != "gc") || (val && val == "gc" && $scope.filters.chcrd && $scope.filters.chcrd == "y")) {
					query.push("iam:" + val);
					tags.push({ ftr: "iam", tag: $filters.iam[val].tag });
					if (val != null && val == "gc" && $scope.filters.chcrd && $scope.filters.chcrd == "y") {
						doquery = true;
					}
				}

				val = $scope.filters.mc;
				if (val == "lg") {
					if (typeof $scope.my_standing == "undefined") {
						val = null;
					} else {
						val = credit_standing_filter_value($scope.my_standing);
					}
				}
				if (val != null) {
					var tn = $filters.mc[val].tag;
					if (has_approval_odds()) {
						query.push("ao:" + val);
						doquery = true;
						switch (val) {
							case "ex":
								tn = "Very Good";
								break;
							case "gd":
								tn = "Good";
								break;
							case "fr":
								tn = "Fair";
								break;
							case "bd":
								tn = "Low";
								break;
						}
						if (tn != null) {
							tn += " Approval Odds";
						}
					} else {
						query.push("mc:" + val);
						uris.push($filters.mc[val].uri);
					}
					// if (!(val == "bd" && $url.uri == "unsecured")) {
					//     tags.push({ftr: "mc", tag: tn});
					// }
				}

				// for uri, "mc" filter comes first
				val = $scope.filters.iam;
				if (val && val != null && val != "gc") {
					uris.push($filters.iam[val].uri);
				}

				var is_bad_credit = $scope.badcredit();

				// IP2-75178 make secured / unsecured as stand alone filter
				if (!$scope.filters.iws.sc || !$scope.filters.iws.us) {
					val = $scope.filters.iws.sc ? "sc" : "us";
					// query.push("iws:" + val);
					uris.push($filters.iws[val].uri);
					tags.push({ ftr: "iws", tag: $filters.iws[val].tag });
				}
				if (is_bad_credit) {
					val = check_toggled_filters("iw", array_diff(Object.keys($filters.iw), ["pch", "bt"]));
					if (val.length > 0) {
						query.push("iw:" + val.join(","));
						for (i = 0; i < val.length; i++) {
							uris.push($filters.iw[val[i]].uri);
							tags.push({ ftr: "iw", subftr: val[i], tag: $filters.iw[val[i]].tag });
						}
					}
				} else {
					val = check_toggled_filters("iw", array_diff(Object.keys($filters.iw), ["sc", "us"]));
					if (val.length > 0) {
						query.push("iw:" + val.join(","));
						for (i = 0; i < val.length; i++) {
							uris.push($filters.iw[val[i]].uri);
							tags.push({ ftr: "iw", subftr: val[i], tag: $filters.iw[val[i]].tag });
						}
					}
				}

				if ($scope.filters.iw.reg) {
					query.push("reg:" + $scope.filters.reg);
					doquery = true;
				}

				// IP2-75178 make reward available for bad credit as well
				// if (!is_bad_credit && $scope.filters.iw.rw && !$scope.filters.rw_all_true) {
				if ($scope.filters.iw.rw && !$scope.filters.rw_all_true) {
					val = check_toggled_filters("rw", Object.keys($filters.rw));
					if (val.length > 0) {
						query.push("rw:" + val.join(","));
						var rw = [];
						for (i = 0; i < val.length; i++) {
							rw.push($filters.rw[val[i]].uri);
						}
						if (rw.length == 1 && uris.length == 1 && uris[0] == "rewards") {
							uris = rw.concat([]);
						} else {
							uris = uris.concat(rw);
						}
					}
				}

				if ((is_bad_credit && (!$scope.filters.nw.vi || !$scope.filters.nw.mc)) || (!is_bad_credit && !$scope.filters.nw_all_true)) {
					val = check_toggled_filters("nw", array_diff(Object.keys($filters.nw), is_bad_credit ? ["am", "di"] : []));
					if (val.length > 0) {
						query.push("nw:" + val.join(","));
						for (i = 0; i < val.length; i++) {
							uris.push($filters.nw[val[i]].uri);
						}
					}
					tags.push({ ftr: "nw", tag: "Card Network" });
				}

				if (!is_bad_credit && $scope.more_filters) {
					if (!$scope.filters.bt_all_true) {
						val = ["n"];
						if ($scope.filters.bt.bt3) {
							val.push("3");
						}
						if ($scope.filters.bt.bt4) {
							val.push("4");
						}
						if ($scope.filters.bt.bt5) {
							val.push("5");
						}
						query.push("bt:" + val.join(","));
						if (val == "n") {
							// bug : This condition will always return 'false' since the types 'string[]' and 'string' have no overlap
							uris.push($filters.bt.n.uri);
						} else {
							doquery = true;
						}
						tags.push({ ftr: "bt", tag: "Balance Transfer Fee" });
					}

					if ($scope.filters.ft == "y") {
						query.push("ft:y");
						uris.push($filters.ft.y.uri);
						tags.push({ ftr: "ft", tag: "No Foreign Transaction Fee" });
					}

					// if (!$scope.filters.emv_all_true) {
					//     val = check_toggled_filters("emv", Object.keys($filters.emv));
					//     if (val.length > 0) {
					//         query.push("emv:" + val.join(","));
					//         if (angular.equals(val, ["pn", "sg"])) {
					//             uris.push($filters.emv.sg.uri);
					//         } else if (val == "pn") { // bug : This condition will always return 'false' since the types 'any[]' and 'string' have no overlap
					//             uris.push($filters.emv.pn.uri);
					//         } else {
					//             doquery = true;
					//         }
					//         tags.push({ftr: "emv", tag: "Smart Chip"});
					//     }
					// }
					val = $scope.filters.emv;
					if (val && val != "n") {
						uris.push($filters.emv[val].uri);
						tags.push({ ftr: "emv", tag: "Smart Chip" });
					}

					if ($scope.filters.pic == "y") {
						query.push("pic:y");
						uris.push($filters.pic.y.uri);
						tags.push({ ftr: "pic", tag: "Picture on Plastic" });
					}

					if ($scope.filters.cha == "y") {
						query.push("cha:y");
						uris.push($filters.cha.y.uri);
						tags.push({ ftr: "cha", tag: "Charity" });
					}

					if (!$scope.filters.inst_pristine) {
						val = [];
						for (i in $scope.filters.inst) {
							if ("invisible" in $scope.filters.inst[i]) {
								if ($scope.filters.inst[i].invisible) {
									continue;
								}
							}
							if ($scope.filters.inst[i].checked) {
								val.push($scope.filters.inst[i].uid);
								j = $scope.filters.inst[i].uri;
							}
						}
						if ($scope.filters.inst_o) {
							val.push("o");
						}
						query.push("inst:" + val.join(","));
						if (val.length == 1 && val != "o" && ["discover", "american-express"].indexOf(j) == -1) {
							// bug : This condition will always return 'true' since the types 'any[]' and 'string' have no overlap
							uris.push(j);
						} else {
							doquery = true;
						}
						tags.push({ ftr: "inst", tag: "Credit Card Companies" });
					}

					if ($scope.filters.stcrd == "y") {
						query.push("stcrd:y");
						uris.push($filters.stcrd.y.uri);
						tags.push({ ftr: "stcrd", tag: "Store Credit Cards" });
					}
					if ($scope.filters.chcrd == "y") {
						query.push("chcrd:y");
						uris.push($filters.chcrd.y.uri);
						tags.push({ ftr: "chcrd", tag: "Charge Cards" });
					}
				}

				if ($scope.filters.srt != "ftr") {
					query.push("srt:" + $scope.filters.srt);
					doquery = true;
				}

				// replace tags
				$scope.filters_tags = tags.slice();

				// replace filters count for mobile
				$scope.total_filters = tags.length;

				// IP2-75178 make secured / unsecured as stand alone filter
				// secured adjustment
				// if (angular.equals(uris, ["bad-credit", "secured"])) {
				//     uris = ["secured"];
				// }

				// check "Other"
				if (get_other_issuer($scope.filters) != null) {
					for (i = 0; i < $scope.filters.inst.length; i++) {
						$scope.filters.inst[i].checked = false;
					}
					$scope.filters.inst_o = true;
				}
				// IP2-75178 disable autoselect mc
				// if ($url.uri == "unsecured") {
				//     $scope.filters.mc = null;
				// }

				// IP2-75178 new filter loc
				var hash = "";
				var force_filter = false;
				if ($scope.filters.loc) {
					// var uri_loc = $scope.filters.loc.replace(/,?\s+/g, '-').toLowerCase();
					// uris.push(uri_loc);
					tags.push({ ftr: "loc", tag: $scope.filters.loc });
					hash = "loc=" + $scope.filters.loc;
					force_filter = true;
				}

				// replace path
				if ($url.entry == "user") {
					var q = angular.copy(qstr);
					if (doquery) {
						q["q"] = query.join(";");
					} else {
						delete q["q"];
					}
					var nuri = uris.length == 0 ? "" : "/" + uris.join("-");
					if ($scope.filtered_page > 1 || $scope.cards_page_change) {
						nuri = $url.uri;
					}
					// - allow watchers to run before making change to the url
					$timeout(function () {
						if (nuri !== null) {
							if (nuri == "" && lpath == "/compare/") {
								nuri = "compare";
							}
							$location
								.path(nuri + "/")
								.hash(hash)
								.search(q);
						} else {
							$location.hash(hash).search(q);
						}
						if (force_filter) refilter();
					});
				}

				// trigger re-paint
				/* if ($scope.show_sidebar_filters) {
                window.requestAnimationFrame(function () {
                    var sb = angular.element().cssSelect(".sidebar")[0];
                    sb.style.display = "none";
                    sb.offsetHeight;
                    sb.style.display = "";
                });
            } */
				// fix iOS voice over changing url
				return null;
			}

			function check_toggled_filters(ftr, val) {
				var ftrs = [],
					i;
				if (ftr in $scope.filters) {
					for (i = 0; i < val.length; i++) {
						if (val[i] in $scope.filters[ftr]) {
							if ($scope.filters[ftr][val[i]]) {
								ftrs.push(val[i]);
							}
						}
					}
				}
				return ftrs;
			}

			function filter_pristine(ftr) {
				if (ftr in $scope.filters && ftr in $filters.defaults) {
					return angular.equals($scope.filters[ftr], $filters.defaults[ftr]);
				}
				return false;
			}

			function filter_make_pristine(ftr) {
				if (filter_pristine(ftr)) {
					return;
				}
				if (ftr in $scope.filters && ftr in $filters.defaults) {
					if (ftr == "loc") {
						$scope.filters.loc_input = "";
					}
					if (ftr == "inst") {
						for (var i in $scope.filters[ftr]) {
							$scope.filters[ftr][i].checked = true;
						}
					} else if (angular.isArray($filters.defaults[ftr])) {
						angular.merge($scope.filters[ftr], $filters.defaults[ftr]);
					} else {
						$scope.filters[ftr] = angular.copy($filters.defaults[ftr]);
					}
				}
			}

			function filters_make_pristine() {
				for (var i = 0; i < arguments.length; i++) {
					filter_make_pristine(arguments[i]);
				}
			}

			// mobile dropdown filters
			$scope.iAmOptions = [
				["General Consumer", "gc"],
				["Business Owner", "bo"],
				["College Student", "cs"],
			];

			$scope.iwOptions = [
				["0% on Purchases", "pch"],
				["0% on Balance Transfers", "bt"],
				["Low Regular Rate", "reg"],
				["No Annual Fee", "af"],
			];

			$scope.drps = {
				iam: "",
				cred: "",
				iw: {
					pch: false,
					bt: false,
					reg: false,
					af: false,
					rw: false,
				},
			};

			$scope.pagChange = function (_$event, dir) {
				if (dir == "next") {
					$scope.filtered_page++;
				} else {
					$scope.filtered_page--;
				}
				$scope.cards_page_change = true;
				// allow watchers of $scope.filtered_page to run before making a change to the url
				$timeout(function () {
					refilter();
				}, 50);
			};

			$scope.load_more_cards = false;
			$scope.showMoreCards = function (_$event, dir) {
				if ($scope.filtering || $scope.load_more_cards) return;

				if (dir == "next") {
					$scope.filtered_page++;
				} else {
					$scope.filtered_page--;
				}
				// $scope.cards_page_change = true;
				$scope.cards_page_change_mob = true;
				$scope.load_more_cards = true;
				// allow watchers of $scope.filtered_page to run before making a change to the url
				$timeout(function () {
					refilter();
				}, 50);
			};

			// don't do anything the first time
			var once = $scope.$watch(
				"filters",
				function (cur, prev) {
					if (angular.equals(cur, prev)) {
						return;
					}
					once();
					$url.entry = "user";
				},
				true
			);

			// dropdow filters select
			$scope.drpselectedClass = {
				iam: !$scope.filters.iam && $scope.filters.chcrd && $scope.filters.chcrd == "y" ? false : true,
				mc: $scope.filters.mc ? true : false,
			};

			$scope.drpselect = {
				iam: function () {
					$timeout(function () {
						$scope.change_filter("iam");
					}, 50);
				},
				mc: function () {
					$timeout(function () {
						if ($scope.filters.mc == "lg") {
							$scope.mycredit_changing = false;
						}
						$scope.change_filter("mc");
					}, 50);
				},
			};
			$scope.drpAfterSelect = {
				iam: function () {
					$timeout(function () {
						if (!$scope.filters.iam && $scope.filters.chcrd && $scope.filters.chcrd == "y") $scope.drpselectedClass.iam = false;
						else $scope.drpselectedClass.iam = true;
					}, 50);
				},
				mc: function () {
					$timeout(function () {
						if ($scope.filters.mc) {
							$scope.drpselectedClass.mc = true;
						} else {
							$scope.drpselectedClass.mc = false;
						}
					}, 50);
				},
			};
			// I want filter on dropdown
			var showing = false;
			$scope.mobIWHolder = "Select Please";
			$scope.mobIW = false;
			$scope.showIW = function (_$event, $deposit) {
				angular.element(document).trigger("click");
				angular.element(document).trigger("vclick");
				if ($scope.mobIW) return;
				$scope.mobIW = true;
				setTimeout(function () {
					$scope.$applyAsync(function () {
						$scope.mobIW = true;
						setTimeout(function () {
							var parentWidth = $viewport.body.prop("clientWidth");
							var drp = angular.element().cssSelect(".iw-checkbox");
							var el = angular.element().cssSelect(".list-iw");
							if ($deposit) {
								drp = angular.element().cssSelect(".iws-checkbox");
								el = angular.element().cssSelect(".list-iws");
							}
							var lf_pos = 0,
								//@ts-ignore
								rt = parentWidth - (el.offset().left + drp.prop("clientWidth")),
								_popup_width = el.prop("clientWidth") + 10;
							if (drp.prop("clientWidth") + rt < _popup_width) {
								lf_pos = drp.prop("clientWidth") + rt - _popup_width - 15;
							}
							el.css({
								left: lf_pos + "px",
							});
						});
					});
					showing = true;
				});
			};
			// IP2-75178 new filter loc
			var showing_loc = false;
			$scope.mobLocHolder = "City, State or Zip";
			$scope.mobLoc = false;
			$scope.showLoc = function (_$event) {
				angular.element(document).trigger("click");
				angular.element(document).trigger("vclick");
				if ($scope.mobLoc) return;
				$scope.mobLoc = true;
				setTimeout(function () {
					$scope.$applyAsync(function () {
						$scope.mobLoc = true;
						$scope.loc_error = false;
						setTimeout(function () {
							var parentWidth = $viewport.body.prop("clientWidth");
							var drp = angular.element().cssSelect(".iw-loc");
							var el = angular.element().cssSelect(".list-loc");
							var lf_pos = 0,
								//@ts-ignore
								rt = parentWidth - (el.offset().left + drp.prop("clientWidth")),
								_popup_width = el.prop("clientWidth") + 10;
							if (drp.prop("clientWidth") + rt < _popup_width) {
								lf_pos = drp.prop("clientWidth") + rt - _popup_width - 15;
							}
							el.css({
								left: lf_pos + "px",
							});
						});
					});
					showing_loc = true;
				});
			};
			$scope.moveToTheList = function ($event) {
				var keyCode = $event.keyCode;
				var _ac_container = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-list");
				var _ac_list_data = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-item");
				// arrow bottom button
				if ((keyCode == 40 || keyCode == 38) && _ac_container.length && _ac_list_data.length) {
					if (!_ac_container.hasClass("ng-hide") && keyCode == 40) {
						_ac_container[0].focus();
					} else {
						_ac_list_data[_ac_list_data.length - 1].focus();
					}
					$event.preventDefault();
					$event.stopPropagation();
				}
				return false;
			};
			$scope.acFocusHandler = function ($event, activeel) {
				requestAnimationFrame(function () {
					var _ac_container = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-list");
					var _ac_list_selected = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-list li.selected");
					if (_ac_container.length && _ac_list_selected.length) {
						var that = _ac_container[0],
							maxHeight = 0,
							realHeight = 0;
						if (!maxHeight) {
							maxHeight = parseInt(_ac_container.css("max-height"));
						}
						if (!realHeight) realHeight = _ac_list_selected[0].offsetHeight;
						if (realHeight) {
							if (!_ac_list_selected) that.scrollTop = 0;
							else {
								var scrTop = that.scrollTop,
									selTop = _ac_list_selected[0].getBoundingClientRect().top - that.getBoundingClientRect().top;
								if (selTop + realHeight - maxHeight > 0) {
									that.scrollTop = selTop + realHeight + scrTop - maxHeight;
								} else if (selTop < 0) {
									that.scrollTop = selTop + scrTop;
								}
							}
						}
					}
				});
			};
			$scope.acBlurHandler = function ($event) {
				requestAnimationFrame(function () {
					var _ac_container = angular.element().cssSelect(".cc-loc-list .ng-autocomplete-list");
					var _ac_input_loc = angular.element().cssSelect(".list-loc .loc-autocomplete");
					if (_ac_input_loc.length && _ac_container.length) {
						_ac_input_loc[0].focus();
						_ac_container[0].scrollTop = 0;
					}
				});
				$event.preventDefault();
				$event.stopPropagation();
				return false;
			};
			$scope.locSelect = function ($event, loc) {
				$scope.filters.loc = loc;
				$scope.filters.loc_input = loc;
				$url.entry = "user";
				$scope.change_filter("loc", loc);
				$scope.$applyAsync(function () {
					showing_loc = false;
					$scope.mobLoc = false;
					$scope.loc_error = false;
				});
			};
			// I want filter on dropdown
			// var showing = false;
			// $scope.mobIWHolder = "Select Please";
			var showing_more = false;
			$scope.drpMore = false;
			$scope.showDrpMore = function (_$event) {
				angular.element(document).trigger("click");
				angular.element(document).trigger("vclick");
				if ($scope.drpMore) return;
				$scope.drpMore = true;
				setTimeout(function () {
					$scope.$applyAsync(function () {
						$scope.drpMore = true;
						setTimeout(function () {
							var parentWidth = $viewport.body.prop("clientWidth");
							var drp = angular.element().cssSelect(".drp-more");
							var el = angular.element().cssSelect(".list-more");
							var lf_pos = 0,
								//@ts-ignore
								rt = parentWidth - (el.offset().left + drp.prop("clientWidth")),
								_popup_width = el.prop("clientWidth") + 10;
							if (drp.prop("clientWidth") + rt < _popup_width) {
								lf_pos = drp.prop("clientWidth") + rt - _popup_width - 15;
							}
							el.css({
								left: lf_pos + "px",
							});
						});
					});
					showing_more = true;
				});
			};
			// mobile sidebar control
			$scope.show_sidebar_filters = false;
			$scope.delayed_filter = false;
			$scope.sidebar_filters_dialog = window.innerWidth <= 1003;
			$scope.cc_plan_text_name = window.innerWidth < 768;
			$scope.filters_dialog_collapsed = false;

			$scope.revealSideBar = function (_$event) {
				$scope.show_sidebar_filters = true;
				setTimeout(function () {
					$scope.$applyAsync(function () {
						$scope.mobIW = false;
						$scope.drpMore = false;
						if (!$scope.filters.loc && $scope.filters.loc_input) {
							$scope.filters.loc_input = "";
						}
					});
					showing = false;
					showing_more = false;
				});
				var header = document.querySelector("#viewport>header"),
					footer = document.querySelector("#viewport>footer");

				header.setAttribute("aria-hidden", "true");
				header.setAttribute("tabindex", "-1");
				footer.setAttribute("aria-hidden", "true");
				footer.setAttribute("tabindex", "-1");
			};
			$scope.hideSideBar = function (_$event) {
				$scope.show_sidebar_filters = false;
				$scope.filters_dialog_collapsed = true;
				if ($scope.delayed_filter) {
					refilter();
					return;
				}
				$timeout(function () {
					$scope.filters_dialog_collapsed = false;
				}, 100);

				var header = document.querySelector("#viewport>header"),
					footer = document.querySelector("#viewport>footer");

				header.removeAttribute("aria-hidden");
				header.removeAttribute("tabindex");
				footer.removeAttribute("aria-hidden");
				footer.removeAttribute("tabindex");
			};

			$scope.disclosure_scroll = function (_$event) {
				if (angular.element().cssSelect(".mob-disclosure").css("display") == "block") {
					$window.scrollTo(0, angular.element().cssSelect(".mob-disclosure").prop("offsetTop") - 50);
					var pj = angular.element().cssSelect(".mob-disclosure p:last-child");
					pj.addClass("yellow");
					pj[0].focus();
					$timeout(function () {
						pj.removeClass("yellow");
					}, 2000);
				} else {
					var pi = angular.element().cssSelect(".sidebar .box:last-child p:last-child");
					$window.scrollTo(0, pi.prop("offsetTop") - 20);
					pi.addClass("yellow");
					pi[0].focus();
					$timeout(function () {
						pi.removeClass("yellow");
					}, 2000);
				}

				return false;
			};

			$scope.disclosure_scroll_bad = function (_$event) {
				$window.scrollTo(0, angular.element().cssSelect(".disclosure p:last-child").prop("offsetTop") - 75);
				angular.element().cssSelect(".disclosure p:last-child").addClass("yellow");
				$timeout(function () {
					angular.element().cssSelect(".disclosure p:last-child").removeClass("yellow");
				}, 2000);
				return false;
			};

			$scope.scroll_toview_bad = function (_$event, category) {
				var top = angular
					.element()
					.cssSelect(".card-container #" + category)
					.prop("offsetTop");
				$window.scrollTo(0, top - 55);
				return false;
			};

			$scope.toggleEditorsContent = function (evt) {
				angular.element(evt.target.parentNode.parentNode).toggleClass("more");
				return false;
			};

			$scope.cards_scroll = function ($event) {
				var cc = angular.element().cssSelect(".card-area-box");
				/** @type {HTMLDivElement} */
				var to_focus = document.querySelector('[data-focus-to="compare"]');
				//@ts-ignore
				angular.element(document).duScrollToElementAnimated(cc, 0, 300);
				//to_focus.setAttribute('aria-hidden','false');
				to_focus.focus();
				setTimeout(function () {
					to_focus.focus();
					/* setTimeout(function(){
                    to_focus.setAttribute('aria-hidden','true');
                },100); */
				});

				$event.preventDefault();
				$event.stopPropagation();
			};

			$scope.discussion_scroll = function (_$event) {
				//@ts-ignore
				angular.element(document).duScrollToElementAnimated(angular.element().cssSelect(".sect-community-discussion .header"), 0, 300);
			};

			$scope.comqa_scroll = function ($event) {
				var el = angular.element().cssSelect(".comqa h2:visible");
				if (el.length == 0) {
					el = angular.element().cssSelect(".sect-community-discussion .header:visible");
				}
				if (el.length == 0) {
					$root.show_ask_overlay = true;
					return;
				}
				//@ts-ignore
				angular.element(document).duScrollToElementAnimated(el, 20, 300);
				el.trigger("focus");
				setTimeout(function () {
					el.trigger("focus");
				});
				$event.preventDefault();
			};
			$scope.secondary_sec_scroll = function ($event, $idx) {
				var el = angular.element().cssSelect(".box-container-picks#editors-picks-" + $idx);
				if (el.length) {
					//@ts-ignore
					angular.element(document).duScrollToElementAnimated(el, 0, 300);
					el.find(".header-part h2").trigger("focus");
					setTimeout(function () {
						el.find(".header-part h2").trigger("focus");
					});
				}
				$event.preventDefault();
			};

			// $animate.on('enter',angular.element().cssSelect('body'),function(el,phase){

			//     if(phase == "start") {
			//         el.on('scroll',function(){
			//             var sc = el.prop('scrollTop');
			//             $scope.$applyAsync(function(){
			//                 $scope.navbarScrolled = sc >= 70;
			//             });
			//         });
			//         angular.element().cssSelect('body').addClass('no-scroll');
			//     }
			// });

			$scope.apply_target = window.innerWidth > 699 ? "_blank" : "_self";

			var docClick = function (ev) {
					var _whitelist = $(ev.target).data("ignoredoc");
					if (_whitelist) return true;

					$scope.$applyAsync(function () {
						$scope.mobIW = false;
						$scope.drpMore = false;
						$scope.mobLoc = false;
						showing = false;
						showing_more = false;
						showing_loc = false;
						if (!$scope.filters.loc && $scope.filters.loc_input) {
							$scope.filters.loc_input = "";
						}
					});
					if (ev && ev.target && ev.target.hash) {
						switch (ev.target.hash.substr(1)) {
							case "qna":
								if (angular.element(".comqa:visible").length == 0) {
									$root.show_ask_overlay = true;
								}
								break;
						}
						ev.preventDefault();
						return false;
					}
				},
				resizeFunc = function () {
					$scope.$applyAsync(function () {
						$scope.show_sidebar_filters = false;
						var ww = window.innerWidth;
						$scope.sidebar_filters_dialog = ww <= 1003;

						$scope.cc_plan_text_name = ww < 768;
						$scope.apply_target = ww > 699 ? "_blank" : "_self";
					});
				};

			var TocClick = function () {
				var target_id = $(this).attr("href");
				if (target_id.indexOf("#") == 0) {
					if (angular.element(target_id).length) {
						$("html,body").animate(
							{
								scrollTop: angular.element(target_id).offset().top,
							},
							300
						);
					}
					return false;
				}
			};

			angular.element(document).on("vclick", docClick);
			angular.element(document).on("click", docClick);
			angular.element(window).on("resize", resizeFunc);
			angular.element(".table-of-contents a").on("vclick", TocClick);
			angular.element(".table-of-contents a").on("click", TocClick);

			$scope.$on("$destroy", function () {
				angular.element(document).off("vclick", docClick);
				angular.element(document).off("click", docClick);
				angular.element(window).off("resize", resizeFunc);
				angular.element(".table-of-contents a").off("vclick", TocClick);
				angular.element(".table-of-contents a").off("click", TocClick);
			});

			if ("v" in $location.search()) {
				// the offset in which to make the header stick in v11
				var con = angular.element(".cards-container"),
					top = con.prop("offsetTop");
				$scope.$watch(
					function () {
						return $window.scrollY > top && $window.scrollY < top + con.prop("clientHeight") - angular.element(".desk-header:first").prop("clientHeight");
					},
					function (stick) {
						$scope.stick = stick;
					},
					true
				);

				// top pagination from>to
				$scope.$watch(
					function () {
						return {
							p: $scope.filtered_page,
							t: page["total_cards"],
							l: $scope.filtered_limit,
						};
					},
					function (o) {
						$scope.res_show_from = (o["p"] - 1) * o["l"] + 1;
						$scope.res_show_to = Math.min(o["t"], $scope.res_show_from + o["l"] - 1);
						$scope.res_show_total = o["t"];
					},
					true
				);
			}

			// if viewport is mobile mode, advanced options is shown by default
			$scope.$watch(
				function () {
					return {
						w: $window.innerWidth,
						sidebar: $scope.show_sidebar_filters,
						compare_page: $root.cardCompare,
					};
				},
				function (dt) {
					$scope.iw = dt.w;
					if (dt.w < 1004) {
						if ($scope.more_filters_old == null) {
							$scope.more_filters_old = $scope.more_filters;
						}
						// $scope.more_filters = !$scope.filters.bt_all_true || $scope.filters.ft == "y" || !$scope.filters.emv_all_true || $scope.filters.pic == "y" || $scope.filters.cha == "y" || !$scope.filters.inst_pristine || $scope.filters.stcrd == "y" || $scope.filters.chcrd == "y";
						$scope.more_filters = !$scope.filters.bt_all_true || $scope.filters.ft == "y" || $scope.filters.pic == "y" || $scope.filters.cha == "y" || !$scope.filters.inst_pristine || $scope.filters.stcrd == "y" || $scope.filters.chcrd == "y" || $scope.filters.emv != "n";
						if (dt.compare_page) {
							return;
						}
						if (dt.sidebar) {
							angular.element().cssSelect("body").addClass("no-scroll");
							angular.element().cssSelect("#searchtool .compare-cc .sidebar").prop("scrollTop", 1); // ios needs 1 not 0
						} else {
							angular.element().cssSelect("body").removeClass("no-scroll");
						}
					} else if ($scope.more_filters_old != null) {
						$scope.more_filters = $scope.more_filters_old;
						delete $scope.more_filters_old;
					}

					if (!has_approval_odds() && $scope.hasCreditStanding) {
						refilter();
					}
				},
				true
			);

			// credit disclosure adjustments
			$scope.showCreditDisclosure = false;
			$scope.creditDisclosure = "The credit score shown on WalletHub is based on your TransUnion credit report as well as the VantageScore 3.0 model, and it may differ from what your lender or insurer uses.";

			var userSc;
			$scope.mobIWSelectedLength = 0;

			$scope.$watch(
				function () {
					return {
						iam: $scope.filters.iam,
						mc: $scope.filters.mc,
						iw: $scope.filters.iw,
						iws: $scope.filters.iws,
						loc: $scope.filters.loc,
						nw: $scope.filters.nw.vi,
						bt: $scope.filters.bt,
						ft: $scope.filters.ft,
						emv: $scope.filters.emv,
						pic: $scope.filters.pic,
						cha: $scope.filters.cha,
						inst: $scope.filters.inst,
						tg: $scope.filters_tags,
						srt: $scope.filters.srt,
						reg: $scope.filters.reg,
						standing: $scope.hasCreditStanding,
						is_mobile: $scope.cc_plan_text_name,
					};
				},
				function (flt, fltp) {
					var iw = [];
					// IP2-75178 make secured / unsecured as stand alone filter
					if ($scope.filters.mc && $scope.filters.mc == "bd") {
						if (!$scope.filters.iws.sc || !$scope.filters.iws.us) {
							iw.push("Deposit");
						}
					} else {
						if ($scope.filters.iw.pch) {
							iw.push("0% on Purchases");
						}
						if ($scope.filters.iw.bt) {
							iw.push("0% on Balance Transfers");
						}
						if ($scope.filters.iw.reg) {
							iw.push("Low Regular Rate");
						}
						if ($scope.filters.iw.af) {
							iw.push("No Annual Fee");
						}
						if ($scope.filters.iw.rw) {
							iw.push("Rewards");
						}
					}
					$scope.mobIWSelected = iw.join(";");
					$scope.mobIWSelectedLength = iw.length;
					/*
            fixed for sonar: `mr` is always empty
            $scope.moreSelected = mr.join(";");
             */
					$scope.moreSelected = "";
					// single i want only
					if (flt.iw.pch) {
						$scope.filters.iwr = "pch";
					} else if (flt.iw.bt) {
						$scope.filters.iwr = "bt";
					} else if (flt.iw.reg) {
						$scope.filters.iwr = "reg";
					} else if (flt.iw.af) {
						$scope.filters.iwr = "af";
					} else {
						$scope.filters.iwr = "rw";
					}
					var fc = 0;
					// IP2-75178 make secured / unsecured as part of more filters
					if (!all_true($scope.filters.bt)) {
						fc++;
					}
					if ($scope.filters.ft == "y") {
						fc++;
					}
					// if (!all_true($scope.filters.emv)) {
					//     fc++;
					// }
					if ($scope.filters.emv && $scope.filters.emv != "n") {
						fc++;
					}
					if ($scope.filters.pic == "y") {
						fc++;
					}
					if ($scope.filters.cha == "y") {
						fc++;
					}
					if (!(all_true($scope.filters.inst) && $scope.filters.inst_o)) {
						fc++;
					}
					if ($scope.filters.stcrd == "y") {
						fc++;
					}
					if ($scope.filters.chcrd == "y") {
						fc++;
					}
					if (!all_true($scope.filters.nw)) {
						fc++;
					}
					if ($scope.filters.mc && $scope.filters.mc == "bd") {
						fc = 0;
						var _mc = [];
						if ($scope.filters.nw && $scope.filters.nw.vi) {
							_mc.push("Visa");
						}
						if ($scope.filters.nw && $scope.filters.nw.mc) {
							_mc.push("Master Card");
						}
						if (_mc.length < 2) {
							fc = 1;
						}
						if ($scope.filters.iw.reg || $scope.filters.iw.af || $scope.filters.iw.rw) {
							fc++;
						}
					} else {
						if (!$scope.filters.iws.sc || !$scope.filters.iws.us) {
							fc++;
						}
					}
					if ($scope.filters.loc && $scope.cc_plan_text_name) {
						fc++;
					}

					$scope.more_filters_count = fc;

					if (flt.reg != fltp.reg) {
						$url.entry = "user";
						$scope.change_filter("reg");
					}

					if (flt.srt != fltp.srt) {
						$url.entry = "user";
						$scope.change_filter("sort");
					}

					if (flt.standing && !userSc) {
						userSc = flt.mc;
					}

					$scope.showCreditDisclosure = flt.standing && (flt.mc == userSc || flt.mc == "lg");
				},
				true
			);

			function LoadExperts() {
				require(["stExperts"], /** @param {typeof import("./experts-controller")} stExperts */ function (stExperts) {
					stExperts.ExpertsInitialize($scope, $injector);
				});
			}

			$stService.onFiltersSet(function (name, value) {
				$scope.filters[name] = value;
				$scope.change_filter(name);
			});
			$stService.ccFiltersReady();
			var scrollpos = document.scrollingElement.scrollTop;
			if (window.location.hash.indexOf("#expert=") === 0 || scrollpos > 100) {
				LoadExperts();
			} else {
				function ScrollWatch() {
					var pos = document.scrollingElement.scrollTop;
					if (pos > 100) {
						window.removeEventListener("scroll", ScrollWatch);
						LoadExperts();
					}
				}
				window.addEventListener("scroll", ScrollWatch);
			}
		},
	]);

	app.pageInjector.get("$stService").setControllerReady("SearchToolCardsController");
});

