/* Minification failed. Returning unminified contents.
(1446,3-4): run-time error JS1195: Expected expression: )
(1449,6-7): run-time error JS1009: Expected '}': [
(1449,13): run-time error JS1004: Expected ';'
(1449,13-14): run-time error JS1195: Expected expression: :
(1450,14): run-time error JS1004: Expected ';'
(1450,14-15): run-time error JS1195: Expected expression: :
(1451,5-6): run-time error JS1195: Expected expression: }
(1460,4-10): run-time error JS1194: Expected ',' or ']': $scope
(1460,4-10): run-time error JS1006: Expected ')': $scope
(1486,4-5): run-time error JS1006: Expected ')': ]
(1486,4): run-time error JS1004: Expected ';'
(1486,4-5): run-time error JS1195: Expected expression: ]
(1486,5-6): run-time error JS1195: Expected expression: )
(1487,1-2): run-time error JS1002: Syntax error: }
(1487,2-3): run-time error JS1195: Expected expression: )
(3806,61): run-time error JS1004: Expected ';'
(3806,71-72): run-time error JS1010: Expected identifier: (
(3819,44): run-time error JS1004: Expected ';'
(3823,47): run-time error JS1004: Expected ';'
(3827,50): run-time error JS1004: Expected ';'
(3855,45-48): run-time error JS1009: Expected '}': ...
(3856,61): run-time error JS1004: Expected ';'
(3856,61-62): run-time error JS1195: Expected expression: :
(3859,42-43): run-time error JS1006: Expected ')': ;
(3863,45-48): run-time error JS1009: Expected '}': ...
(3864,53): run-time error JS1004: Expected ';'
(3864,53-54): run-time error JS1195: Expected expression: :
(3867,42-43): run-time error JS1006: Expected ')': ;
(3871,34): run-time error JS1004: Expected ';'
(3871,34-35): run-time error JS1195: Expected expression: )
(3872,30-31): run-time error JS1009: Expected '}': )
(3693,21): run-time error JS1004: Expected ';'
(3872,30-31): run-time error JS1195: Expected expression: )
(3873,29-30): run-time error JS1195: Expected expression: .
(3876,21-30): run-time error JS1194: Expected ',' or ']': SearchBar
(3876,21-30): run-time error JS1006: Expected ')': SearchBar
(3901,13-14): run-time error JS1006: Expected ')': }
(3901,13-14): run-time error JS1002: Syntax error: }
(3903,9-10): run-time error JS1002: Syntax error: }
(3903,10-11): run-time error JS1195: Expected expression: ]
(3903,11-12): run-time error JS1195: Expected expression: )
(3904,1-2): run-time error JS1002: Syntax error: }
(3904,4): run-time error JS1004: Expected ';'
(3904,4-5): run-time error JS1195: Expected expression: )
(4254,40-43): run-time error JS1009: Expected '}': ...
(4254,40-43): run-time error JS1006: Expected ')': ...
(4254,40): run-time error JS1004: Expected ';'
(4254,79-80): run-time error JS1033: Expected 'catch': )
(4254,79-80): run-time error JS1195: Expected expression: )
(4255,5): run-time error JS1004: Expected ';'
(4255,6-11): run-time error JS1195: Expected expression: catch
(4255,15): run-time error JS1004: Expected ';'
(4260,2-3): run-time error JS1006: Expected ')': }
(4259,4): run-time error JS1004: Expected ';'
(4260,3-4): run-time error JS1195: Expected expression: )
(4310,22-24): run-time error JS1009: Expected '}': =>
(4310,13-21): run-time error JS1317: Unable to convert from reference to binding: async ()
(4316,17): run-time error JS1004: Expected ';'
(4323,49-52): run-time error JS1009: Expected '}': ...
(4323,49): run-time error JS1004: Expected ';'
(4323,62): run-time error JS1004: Expected ';'
(4323,62-63): run-time error JS1195: Expected expression: :
(4323,67-68): run-time error JS1006: Expected ')': ;
(4324,6-7): run-time error JS1006: Expected ')': }
(4324,8): run-time error JS1004: Expected ';'
(4324,8-9): run-time error JS1195: Expected expression: )
(4334,6): run-time error JS1004: Expected ';'
(4334,6-7): run-time error JS1195: Expected expression: )
(4336,3-4): run-time error JS1006: Expected ')': }
(4338,1-2): run-time error JS1002: Syntax error: }
(4338,2-3): run-time error JS1195: Expected expression: )
(4443,5-8): run-time error JS1009: Expected '}': ...
(4445,14): run-time error JS1004: Expected ';'
(4445,14-15): run-time error JS1195: Expected expression: :
(4446,20): run-time error JS1004: Expected ';'
(4446,20-21): run-time error JS1195: Expected expression: :
(4447,16): run-time error JS1004: Expected ';'
(4447,16-17): run-time error JS1195: Expected expression: :
(4447,20-21): run-time error JS1195: Expected expression: ,
(4525,2-8): run-time error JS1006: Expected ')': window
(4526,1-2): run-time error JS1002: Syntax error: }
(4526,2-3): run-time error JS1195: Expected expression: )
(4591,7-10): run-time error JS1009: Expected '}': ...
(4591,7-10): run-time error JS1006: Expected ')': ...
(4597,14): run-time error JS1004: Expected ';'
(4597,14-15): run-time error JS1195: Expected expression: :
(4598,6-7): run-time error JS1195: Expected expression: }
(4599,6-7): run-time error JS1033: Expected 'catch': )
(4599,6-7): run-time error JS1195: Expected expression: )
(4600,5): run-time error JS1004: Expected ';'
(4600,6-11): run-time error JS1195: Expected expression: catch
(4600,19): run-time error JS1004: Expected ';'
(4603,4-5): run-time error JS1006: Expected ')': ;
(4645,7-10): run-time error JS1009: Expected '}': ...
(4645,7-10): run-time error JS1006: Expected ')': ...
(4644,24): run-time error JS1004: Expected ';'
(4646,21): run-time error JS1004: Expected ';'
(4646,21-22): run-time error JS1195: Expected expression: :
(4647,7-8): run-time error JS1195: Expected expression: )
(4648,6-10): run-time error JS1006: Expected ')': else
(4648,5): run-time error JS1004: Expected ';'
(4653,7-10): run-time error JS1009: Expected '}': ...
(4653,7-10): run-time error JS1006: Expected ')': ...
(4652,24): run-time error JS1004: Expected ';'
(4654,21): run-time error JS1004: Expected ';'
(4654,21-22): run-time error JS1195: Expected expression: :
(4655,6-7): run-time error JS1195: Expected expression: }
(4655,7-8): run-time error JS1195: Expected expression: )
(4657,3-4): run-time error JS1006: Expected ')': }
(4657,3-4): run-time error JS1002: Syntax error: }
(4657,4-5): run-time error JS1195: Expected expression: )
(4694,2-3): run-time error JS1002: Syntax error: }
(4694,3-4): run-time error JS1195: Expected expression: )
(4695,1-2): run-time error JS1002: Syntax error: }
(4695,2-3): run-time error JS1195: Expected expression: )
(5036,5-8): run-time error JS1009: Expected '}': ...
(5037,11): run-time error JS1004: Expected ';'
(5037,11-12): run-time error JS1195: Expected expression: :
(5038,4-5): run-time error JS1195: Expected expression: }
(5047,28-31): run-time error JS1009: Expected '}': ...
(5047,28-31): run-time error JS1006: Expected ')': ...
(5047,28): run-time error JS1004: Expected ';'
(5047,52): run-time error JS1004: Expected ';'
(5047,52-53): run-time error JS1195: Expected expression: :
(5053,3-9): run-time error JS1006: Expected ')': return
(5058,15-18): run-time error JS1009: Expected '}': ...
(5058,15-18): run-time error JS1009: Expected '}': ...
(5058,15-18): run-time error JS1006: Expected ')': ...
(5058,18-25): run-time error JS1009: Expected '}': headers
(5053,11): run-time error JS1004: Expected ';'
(5058,46): run-time error JS1004: Expected ';'
(5058,46-47): run-time error JS1195: Expected expression: :
(5058,74-75): run-time error JS1002: Syntax error: }
(5059,4-5): run-time error JS1002: Syntax error: }
(5059,5-6): run-time error JS1195: Expected expression: )
(5059,6-7): run-time error JS1195: Expected expression: ,
(5060,3-4): run-time error JS1002: Syntax error: }
(5061,2-3): run-time error JS1002: Syntax error: }
(5061,3-4): run-time error JS1195: Expected expression: )
(5081,1-2): run-time error JS1002: Syntax error: }
(5081,2-3): run-time error JS1195: Expected expression: )
(5306,6-9): run-time error JS1009: Expected '}': ...
(5307,10): run-time error JS1004: Expected ';'
(5307,10-11): run-time error JS1195: Expected expression: :
(5308,12): run-time error JS1004: Expected ';'
(5308,12-13): run-time error JS1195: Expected expression: :
(5309,5-6): run-time error JS1195: Expected expression: }
(5327,2-3): run-time error JS1006: Expected ')': }
(5326,4): run-time error JS1004: Expected ';'
(5327,3-4): run-time error JS1195: Expected expression: )
(6169,16-17): run-time error JS1195: Expected expression: =
(6169,16-17): run-time error JS1012: Illegal assignment: =
(6170,18-19): run-time error JS1195: Expected expression: =
(6170,18-19): run-time error JS1012: Illegal assignment: =
(6171,18-19): run-time error JS1195: Expected expression: =
(6171,18-19): run-time error JS1012: Illegal assignment: =
(6172,20-21): run-time error JS1195: Expected expression: =
(6172,20-21): run-time error JS1012: Illegal assignment: =
(6876,7-10): run-time error JS1009: Expected '}': ...
(6876,7-10): run-time error JS1006: Expected ')': ...
(6876,7-10): run-time error JS1006: Expected ')': ...
(6875,44): run-time error JS1004: Expected ';'
(6877,12): run-time error JS1004: Expected ';'
(6877,12-13): run-time error JS1195: Expected expression: :
(6878,15): run-time error JS1004: Expected ';'
(6878,15-16): run-time error JS1195: Expected expression: :
(6879,11): run-time error JS1004: Expected ';'
(6879,11-12): run-time error JS1195: Expected expression: :
(6880,6-7): run-time error JS1195: Expected expression: }
(6880,8): run-time error JS1004: Expected ';'
(6880,8-9): run-time error JS1195: Expected expression: )
(6881,6): run-time error JS1004: Expected ';'
(6881,6-7): run-time error JS1195: Expected expression: )
(6884,4-12): run-time error JS1009: Expected '}': $timeout
(6884,4-12): run-time error JS1006: Expected ')': $timeout
(6884,4-12): run-time error JS1194: Expected ',' or ']': $timeout
(6884,4-12): run-time error JS1006: Expected ')': $timeout
(6888,2-3): run-time error JS1006: Expected ')': }
(6888,2-3): run-time error JS1002: Syntax error: }
(6888,3-4): run-time error JS1195: Expected expression: )
(6888,4-5): run-time error JS1195: Expected expression: ]
(6888,5-6): run-time error JS1195: Expected expression: )
(6898,1-2): run-time error JS1002: Syntax error: }
(6898,2-3): run-time error JS1195: Expected expression: )
(7314,8-11): run-time error JS1009: Expected '}': ...
(7314,8-11): run-time error JS1006: Expected ')': ...
(7314,8-11): run-time error JS1006: Expected ')': ...
(7313,61): run-time error JS1004: Expected ';'
(7315,12): run-time error JS1004: Expected ';'
(7315,12-13): run-time error JS1195: Expected expression: :
(7316,9): run-time error JS1004: Expected ';'
(7316,9-10): run-time error JS1195: Expected expression: )
(7317,7-8): run-time error JS1195: Expected expression: )
(7321,2-3): run-time error JS1006: Expected ')': }
(7320,4): run-time error JS1004: Expected ';'
(7321,3-4): run-time error JS1195: Expected expression: )
(7365,6-9): run-time error JS1009: Expected '}': ...
(7365,6-9): run-time error JS1006: Expected ')': ...
(7364,47): run-time error JS1004: Expected ';'
(7366,11): run-time error JS1004: Expected ';'
(7366,11-12): run-time error JS1195: Expected expression: :
(7367,13): run-time error JS1004: Expected ';'
(7367,13-14): run-time error JS1195: Expected expression: :
(7368,10): run-time error JS1004: Expected ';'
(7368,10-11): run-time error JS1195: Expected expression: :
(7369,17): run-time error JS1004: Expected ';'
(7369,17-18): run-time error JS1195: Expected expression: :
(7370,23): run-time error JS1004: Expected ';'
(7370,23-24): run-time error JS1195: Expected expression: :
(7371,5-6): run-time error JS1195: Expected expression: }
(7377,5-6): run-time error JS1195: Expected expression: )
(7380,3-9): run-time error JS1194: Expected ',' or ']': return
(7380,3-9): run-time error JS1006: Expected ')': return
(7347,37): run-time error JS1004: Expected ';'
(7383,8): run-time error JS1004: Expected ';'
(7383,8-9): run-time error JS1195: Expected expression: :
(7384,10): run-time error JS1004: Expected ';'
(7384,10-11): run-time error JS1195: Expected expression: :
(7385,10): run-time error JS1004: Expected ';'
(7385,10-11): run-time error JS1195: Expected expression: :
(7386,11): run-time error JS1004: Expected ';'
(7386,11-12): run-time error JS1195: Expected expression: :
(7387,4-5): run-time error JS1195: Expected expression: }
(7387,5-6): run-time error JS1195: Expected expression: ,
(7388,36): run-time error JS1004: Expected ';'
(7400,20-21): run-time error JS1195: Expected expression: =
(7400,20-21): run-time error JS1012: Illegal assignment: =
(7408,3-4): run-time error JS1006: Expected ')': ]
(7408,3): run-time error JS1004: Expected ';'
(7408,3-4): run-time error JS1195: Expected expression: ]
(7408,4-5): run-time error JS1195: Expected expression: )
(7409,1-2): run-time error JS1002: Syntax error: }
(7409,2-3): run-time error JS1195: Expected expression: )
(8182,31-34): run-time error JS1009: Expected '}': ...
(8182,31): run-time error JS1004: Expected ';'
(8182,52): run-time error JS1004: Expected ';'
(8182,52-53): run-time error JS1195: Expected expression: :
(8182,71-72): run-time error JS1006: Expected ')': ;
(8182,71-72): run-time error JS1006: Expected ')': ;
(8212,12): run-time error JS1004: Expected ';'
(8212,12-13): run-time error JS1195: Expected expression: )
(8213,7): run-time error JS1004: Expected ';'
(8213,7-8): run-time error JS1195: Expected expression: )
(8217,2-3): run-time error JS1194: Expected ',' or ']': }
(8217,2-3): run-time error JS1006: Expected ')': }
(8161,40): run-time error JS1004: Expected ';'
(8217,3-4): run-time error JS1195: Expected expression: ]
(8217,4-5): run-time error JS1195: Expected expression: )
(8280,6-9): run-time error JS1009: Expected '}': ...
(8281,5-6): run-time error JS1195: Expected expression: }
(8281,6-7): run-time error JS1009: Expected '}': ;
(8395,3-4): run-time error JS1006: Expected ')': }
(8414,1-2): run-time error JS1002: Syntax error: }
(8414,2-3): run-time error JS1195: Expected expression: )
(10147,8): run-time error JS1004: Expected ';'
(10149,32): run-time error JS1004: Expected ';'
(10152,8): run-time error JS1004: Expected ';'
(10155,9): run-time error JS1004: Expected ';'
(10190,8): run-time error JS1004: Expected ';'
(10191,16): run-time error JS1004: Expected ';'
(10194,8): run-time error JS1004: Expected ';'
(10195,19): run-time error JS1004: Expected ';'
(10199,8): run-time error JS1004: Expected ';'
(10204,8): run-time error JS1004: Expected ';'
(10206,22): run-time error JS1004: Expected ';'
(10210,8): run-time error JS1004: Expected ';'
(10211,16): run-time error JS1004: Expected ';'
(10222,8): run-time error JS1004: Expected ';'
(10235,22): run-time error JS1004: Expected ';'
(10241,8): run-time error JS1004: Expected ';'
(10250,37): run-time error JS1004: Expected ';'
(10263,5-8): run-time error JS1009: Expected '}': ...
(10264,8): run-time error JS1004: Expected ';'
(10264,8-9): run-time error JS1195: Expected expression: :
(10265,4-5): run-time error JS1195: Expected expression: }
(10268,8): run-time error JS1004: Expected ';'
(10269,22): run-time error JS1004: Expected ';'
(10273,5-8): run-time error JS1009: Expected '}': ...
(10274,11): run-time error JS1004: Expected ';'
(10274,11-12): run-time error JS1195: Expected expression: :
(10278,3-9): run-time error JS1006: Expected ')': $scope
(10335,26): run-time error JS1004: Expected ';'
(10335,36-37): run-time error JS1010: Expected identifier: (
(10369,9): run-time error JS1004: Expected ';'
(10376,32): run-time error JS1004: Expected ';'
(10376,42-43): run-time error JS1010: Expected identifier: (
(10382,30): run-time error JS1004: Expected ';'
(10407,10): run-time error JS1004: Expected ';'
(10491,37): run-time error JS1004: Expected ';'
(10491,47-48): run-time error JS1010: Expected identifier: (
(10492,9): run-time error JS1004: Expected ';'
(10499,33): run-time error JS1004: Expected ';'
(10499,43-44): run-time error JS1010: Expected identifier: (
(10518,9): run-time error JS1004: Expected ';'
(10523,36): run-time error JS1004: Expected ';'
(10523,46-47): run-time error JS1010: Expected identifier: (
(10536,9): run-time error JS1004: Expected ';'
(10556,90-92): run-time error JS1006: Expected ')': =>
(10556,89): run-time error JS1004: Expected ';'
(10567,58): run-time error JS1004: Expected ';'
(10568,51): run-time error JS1004: Expected ';'
(10591,10): run-time error JS1004: Expected ';'
(10605,26): run-time error JS1004: Expected ';'
(10607,32): run-time error JS1004: Expected ';'
(10609,25): run-time error JS1004: Expected ';'
(10611,48): run-time error JS1004: Expected ';'
(10613,10): run-time error JS1004: Expected ';'
(10623,4-5): run-time error JS1195: Expected expression: )
(10642,2-3): run-time error JS1002: Syntax error: }
(10651,1-2): run-time error JS1002: Syntax error: }
(10651,2-3): run-time error JS1195: Expected expression: )
(10660,22-25): run-time error JS1009: Expected '}': ...
(10660,22-25): run-time error JS1006: Expected ')': ...
(10660,22): run-time error JS1004: Expected ';'
(10660,44): run-time error JS1004: Expected ';'
(10660,44-45): run-time error JS1195: Expected expression: )
(10695,2-8): run-time error JS1006: Expected ')': window
(10704,1-2): run-time error JS1002: Syntax error: }
(10704,2-3): run-time error JS1195: Expected expression: )
(10804,40): run-time error JS1004: Expected ';'
(10804,50-51): run-time error JS1010: Expected identifier: (
(10806,22): run-time error JS1004: Expected ';'
(10811,5-8): run-time error JS1009: Expected '}': ...
(10812,11): run-time error JS1004: Expected ';'
(10812,11-12): run-time error JS1195: Expected expression: :
(10816,37): run-time error JS1004: Expected ';'
(10816,47-48): run-time error JS1010: Expected identifier: (
(10824,36): run-time error JS1004: Expected ';'
(10880,25): run-time error JS1004: Expected ';'
(10880,35-36): run-time error JS1010: Expected identifier: (
(10907,9): run-time error JS1004: Expected ';'
(10916,32): run-time error JS1004: Expected ';'
(10916,42-43): run-time error JS1010: Expected identifier: (
(10935,9): run-time error JS1004: Expected ';'
(10940,35): run-time error JS1004: Expected ';'
(10940,45-46): run-time error JS1010: Expected identifier: (
(10950,9): run-time error JS1004: Expected ';'
(10977,2-8): run-time error JS1006: Expected ')': window
(10987,1-2): run-time error JS1002: Syntax error: }
(10987,2-3): run-time error JS1195: Expected expression: )
(11198,7-10): run-time error JS1009: Expected '}': ...
(11198,7-10): run-time error JS1006: Expected ')': ...
(11198,7-10): run-time error JS1006: Expected ')': ...
(11197,66): run-time error JS1004: Expected ';'
(11199,10): run-time error JS1004: Expected ';'
(11199,10-11): run-time error JS1195: Expected expression: :
(11200,19): run-time error JS1004: Expected ';'
(11200,19-20): run-time error JS1195: Expected expression: :
(11201,12): run-time error JS1004: Expected ';'
(11201,12-13): run-time error JS1195: Expected expression: :
(11202,6-7): run-time error JS1195: Expected expression: }
(11202,8): run-time error JS1004: Expected ';'
(11202,8-9): run-time error JS1195: Expected expression: )
(11203,6-7): run-time error JS1009: Expected '}': )
(11192,11): run-time error JS1004: Expected ';'
(11203,6-7): run-time error JS1195: Expected expression: )
(11205,3-4): run-time error JS1195: Expected expression: }
(11205,3-4): run-time error JS1194: Expected ',' or ']': }
(11205,3-4): run-time error JS1006: Expected ')': }
(11206,3-4): run-time error JS1006: Expected ')': ]
(11206,3): run-time error JS1004: Expected ';'
(11206,3-4): run-time error JS1195: Expected expression: ]
(11206,4-5): run-time error JS1195: Expected expression: )
(11207,1-2): run-time error JS1002: Syntax error: }
(11207,2-3): run-time error JS1195: Expected expression: )
(11480,20): run-time error JS1004: Expected ';'
(11480,30-31): run-time error JS1010: Expected identifier: (
(11492,26): run-time error JS1004: Expected ';'
(11591,7-10): run-time error JS1009: Expected '}': ...
(11591,7-10): run-time error JS1006: Expected ')': ...
(11591,7-10): run-time error JS1006: Expected ')': ...
(11590,54): run-time error JS1004: Expected ';'
(11592,10): run-time error JS1004: Expected ';'
(11592,10-11): run-time error JS1195: Expected expression: :
(11593,19): run-time error JS1004: Expected ';'
(11593,19-20): run-time error JS1195: Expected expression: :
(11594,11): run-time error JS1004: Expected ';'
(11594,11-12): run-time error JS1195: Expected expression: :
(11595,12): run-time error JS1004: Expected ';'
(11595,12-13): run-time error JS1195: Expected expression: :
(11596,6-7): run-time error JS1195: Expected expression: }
(11596,8): run-time error JS1004: Expected ';'
(11596,8-9): run-time error JS1195: Expected expression: )
(11598,6): run-time error JS1004: Expected ';'
(11598,6-7): run-time error JS1195: Expected expression: )
(11600,2-3): run-time error JS1194: Expected ',' or ']': }
(11600,2-3): run-time error JS1006: Expected ')': }
(11580,48): run-time error JS1004: Expected ';'
(11600,3-4): run-time error JS1195: Expected expression: ]
(11600,4-5): run-time error JS1195: Expected expression: )
(11608,24-32): run-time error JS1009: Expected '}': function
(11607,11): run-time error JS1004: Expected ';'
(11608,33-34): run-time error JS1010: Expected identifier: (
(11609,23): run-time error JS1004: Expected ';'
(11621,5-6): run-time error JS1195: Expected expression: ,
(11623,2-3): run-time error JS1006: Expected ')': }
(11622,4): run-time error JS1004: Expected ';'
(11623,3-4): run-time error JS1195: Expected expression: )
(11908,22-25): run-time error JS1009: Expected '}': ...
(11908,22-25): run-time error JS1006: Expected ')': ...
(11908,22): run-time error JS1004: Expected ';'
(11908,44): run-time error JS1004: Expected ';'
(11908,44-45): run-time error JS1195: Expected expression: )
(11931,1-2): run-time error JS1006: Expected ')': }
(11931,1-2): run-time error JS1002: Syntax error: }
(11931,4): run-time error JS1004: Expected ';'
(11931,4-5): run-time error JS1195: Expected expression: )
(12583,39-40): run-time error JS1195: Expected expression: .
(12583,84-85): run-time error JS1003: Expected ':': ;
(1083,3,1200,4): run-time error JS1314: Implicit property name must be identifier: link(scope, elem) {
			const paypalOverlay = angular.element('<div class="paypal-overlay"></div>');
			
			const createOrder = (data, actions) => {
				scope.$emit('checkout.busy');
				scope.$broadcast('checkout.busy');
				
				const model = scope.data.model;
				
				const shippingPref = $paypalAddress ? "SET_PROVIDED_ADDRESS" : "NO_SHIPPING";
				
				const address = $paypalAddress ? {
					"admin_area_2": $paypalAddress.City,
					"postal_code": $paypalAddress.PostalCode,
					"country_code": $paypalAddress.CountryCode,
					"address_line_1": $paypalAddress.AddressLine1,
				} : {};
				
				const items = model.ShoppingBag.Items.map(item => ({
					"quantity": 1,
					"name": item.Sku.ProductCode,
					"description": item.Sku.ProductName,
					"unit_amount": {
						"currency_code": "USD",
						"value": item.TotalAmount,
					},
				}));
				
				return actions.order.create({
					"purchase_units": [
						{
							"description": "Tile & Stone",
							"amount": {
								"value": model.AmountDue,
								"currency_code": "USD",
								"breakdown": {
									"item_total": {
										"currency_code": "USD",
										"value": model.ShoppingBag.SubTotal
									},
									"shipping": {
										"currency_code": "USD",
										"value": model.ShoppingBag.ShippingAmount
									},
									"tax_total": {
										"currency_code": "USD",
										"value": model.TaxAmount
									},
									"handling": {
										"currency_code": "USD",
										"value": model.MiscChargesAmount
									},
								}
							},
							"items": items,
							"shipping": {address},
						}
					],
					"application_context": {
						"brand_name": "Bedrosians",
						"shipping_preference": shippingPref,
					}
				});
			};
			
			const onApprove = (data, actions) => {
				actions.order.authorize().then(function (authorization) {
					scope.$emit('checkout.busy');
					scope.$broadcast('checkout.busy');
					let success = authorization.status === "COMPLETED";
					let authorizationID = authorization.purchase_units[0].payments.authorizations[0].id;
					window.location = `${$paypalAction}?success=${success}&orderId=${data.orderID}&authorizationId=${authorizationID}`;
				});
			};
			
			const onCancel = () => {
				scope.$emit('checkout.ready');
				scope.$broadcast('checkout.ready');
			};
			
			const onInit = (data, actions) => {
				actions.disable();
				scope.$watch('data.model.ShoppingBag', (value) => {
					if (!value) {
						actions.disable();
						elem.append(paypalOverlay);
					} else {
						actions.enable();
						paypalOverlay.remove();
					}
				});
			}
			
			const onError = (error) => {
				scope.$emit('checkout.ready');
				scope.$broadcast('checkout.ready');
				alert("An error occurred, please try again or try an alternate form of payment.")
			};
			
			const node = elem.get(0);
			
			const style = {
				color: "black",
				borderRadius: 12,
				label: "checkout",
			};
			
			elem.append(paypalOverlay);
			
			paypal.Buttons({
				style,
				onInit,
				onError,
				onCancel,
				onApprove,
				createOrder,
			}).render(node);
		}
(1213,4,1231,5): run-time error JS1314: Implicit property name must be identifier: submit(event) {
				event.preventDefault();

				if ($scope.registrationForm.$invalid) return;

				if (!grecaptcha) return;

				grecaptcha.ready(() => {
					return grecaptcha.execute($scope.form.recaptchaToken, {action: "QuickRegister"})
						.then((token) => {
							$timeout(() => {
								$scope.$apply(() => {
									$scope.form.recaptchaToken = token;
									$timeout(() => event.target.submit());
								});
							})
						});
				});
			}
(2588,4,2598,5): run-time error JS1314: Implicit property name must be identifier: compile(element) {
				const update = () => {
					const offset = element.parent().offset();
					element.css('top', `${offset.top}px`);
					element.css('position', 'sticky');
				}
				
				window.addEventListener('resize', update);
				
				update();
			}
(2675,43,2683,6): run-time error JS1314: Implicit property name must be identifier: completed() {
					$timeout(() => {
						scope.$apply(() => {
							let value = this.val().toString();
							$ctrl.$setViewValue(value);
							element.val(value);
						});
					});
				}
(2672,3,2685,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attrs, $ctrl) {
			let mask = attrs['commonMask'];
			element.mask(mask, {
				selectOnFocus: true, autoclear: true, completed() {
					$timeout(() => {
						scope.$apply(() => {
							let value = this.val().toString();
							$ctrl.$setViewValue(value);
							element.val(value);
						});
					});
				}
			});
		}
(2781,17,2789,4): run-time error JS1314: Implicit property name must be identifier: link(scope, elem, attrs) {
			let callback = ($parse(attrs.gAutocomplete))(scope);
			uiGmapGoogleMapApi.then(maps => {
				let node = elem.get(0);
				scope.component = new maps.places.Autocomplete(node);
				scope.component.addListener('place_changed', () => callback(scope.component));
				attrs.gAutocompleteRestriction && scope.$watch(attrs.gAutocompleteRestriction, (value) => scope.component.setComponentRestrictions({country: [value]}));
			});
		}
(2860,3,2925,4): run-time error JS1314: Implicit property name must be identifier: compile($element, attrs, linker) {
			let tiles = {};
			
			$element.masonry({
				percentPosition: true,
				horizontalOrder: false,
				columnWidth: '.masonry-item',
				itemSelector: '.masonry-item',
			});
			
			return (scope) => {
				const addTile = (item, last) => {
					let inner = scope.$new(false);
					inner['image'] = item;
					inner['$last'] = last;
					return linker(inner, (clone) => {
						tiles[item.id] = {
							scope: inner,
							element: clone,
							collectionItem: item,
						};
						return $timeout(() => {
							$element.append(clone).masonry('appended', clone).masonry('layout');
							clone.find('img').on('load', function (event) {
								angular.element(event.target).off('load', this);
								$element.masonry('layout');
							});
						});
					});
				};
				
				scope.$on('masonry.clean', () => {
					for (let key in tiles) {
						const item = tiles[key];
						$element.masonry('remove', item.element);
						item.scope.$destroy();
						delete tiles[key];
					}
					$element.masonry('layout');
				});
				
				return scope.$watchCollection(attrs.masonry, (newCollection) => {
					if (!(newCollection != null ? newCollection.length : void 0)) return;
					
					for (const key in tiles) {
						if (!newCollection.some(item => item.id === key)) {
							const item = tiles[key];
							$element.masonry('remove', item.element);
							item.scope.$destroy();
							delete tiles[key];
						}
					}
					
					newCollection.forEach((item, index) => {
						const last = index === newCollection.length - 1;
						if (tiles[item.id]) {
							tiles[item.id].scope.$last = last;
						} else {
							addTile(item, last);
						}
					});
					
					$element.masonry('layout');
				});
			};
		}
(2944,3,2949,4): run-time error JS1314: Implicit property name must be identifier: link(scope) {
			scope.data = {open: false};
			scope.open = () => scope.data.open = true;
			scope.close = () => scope.data.open = false;
			scope.toggle = () => scope.data.open = !scope.data.open;
		}
(2996,3,3001,4): run-time error JS1314: Implicit property name must be identifier: compile(elem, attrs) {
			return (scope) => {
				elem.removeAttr('title');
				scope.title = attrs.title;
			}
		}
(3922,17,3930,4): run-time error JS1314: Implicit property name must be identifier: link(scope, elem, attrs) {
			if (!attrs.paymentActionsWatch) return;
			let actions = ($parse(attrs.paymentActions))(scope);
			scope.$watch(attrs.paymentActionsWatch, (value) => {
				if(!value) return;
				let action = Object.entries(actions).find(([key]) => key === value)[1];
				elem.attr('action', action);
			});
		}
(4929,4,4932,5): run-time error JS1314: Implicit property name must be identifier: inject(services) {
				let keys = Object.keys(services);
				keys.map(key => injector.has(services[key]) && (scope[key] = injector.get(services[key])));
			}
(5338,5,5351,6): run-time error JS1314: Implicit property name must be identifier: link(scope, elem, attrs) {
					let key = ($parse(attrs.bdAccordion))(scope);
					let preopen = ($parse(attrs.bdAccordionPreopen))(scope);
					elem.removeAttr('bd-accordion');
					const toggle = () => {
						let container = angular.element(`[data-key="${key}"]`);
						container.slideToggle('slow');
						elem.toggleClass('bd-filter-title-open');
						// elem.toggleClass('bd-filter-open');
					}
					scope.$on('$destroy', () => elem.off('click', toggle));
					elem.on('click', toggle);
					preopen && toggle();
				}
(6103,3,6107,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes) {
			scope.brandId = attributes.brandId;
			const tag = $compile(template)(scope);
			element.replaceWith(tag);
		}
(6166,3,6260,4): run-time error JS1314: Implicit property name must be identifier: compile(elem, attrs, linker) {
			elem.remove();
			return (scope) => {
				scope.to ||= 'body';
				scope.open ||= false;
				scope.left ||= false;
				scope.opened ||= false;
				const html = angular.element('html');
				const body = angular.element('body');
				const placement = angular.element(scope.to);
				const drawer = angular.element('<div class="bd-drawer"></div>');
				const open = () => {
					const topScroll = window.scrollY;
					const scroll = window.innerWidth - document.body.clientWidth;

					html.css({
						height: '100%',
						overflow: 'hidden',
						paddingRight: scroll + 'px',
					});

					const content = $compile(contentTemplate)(scope);
					return linker(scope.$parent, (copy, slotScope) => {
						slotScope.$on('$destroy', () => content.remove());

						const slot = content.find('slot');
						if (slot) slot.replaceWith(copy);

						drawer.css({
							top: 0,
							left: '0',
							width: '100%',
							height: '100%',
							position: 'fixed',
							overflow: 'hidden',
							justifyContent: scope.left ? 'flex-start' : 'flex-end',
						});

						drawer.on('scroll', (event) => event.preventDefault());
						drawer.on('click', drawerClick);
						drawer.addClass('bd-drawer-in');
						drawer.empty().append(content);
						placement.append(drawer);
						scope.opened = true;
					});
				}
				const close = () => {
					html.css({
						height: '',
						overflow: '',
						paddingRight: '',
					});

					if (!scope.opened) return;

					drawer.addClass('bd-drawer-out');
					drawer.removeClass('bd-drawer-in');
					drawer.on('animationend', animationEnd);
				}

				const watcher = scope.$watch('open', (value) => value ? open() : close());

				const drawerClick = function (event) {
					scope.$apply(() => {
						if (event.target === this || event.target.dataset.close)
							scope.open = false;
					});
				}

				const animationEnd = () => {
					scope.$apply(() => {
						scope.opened = false;
						drawer.remove();
						if (scope.close) scope.close();
						drawer.removeClass('bd-drawer-out');
						drawer.off('animationend', animationEnd);
					});
				}

				const keyHandler = (event) => {
					scope.$apply(() => {
						if (event.key === 'Escape') scope.open = false;
					});
				}

				angular.element(document).on('keydown', keyHandler);

				scope.$on('$destroy', () => {
					angular.element(document).off('keydown', keyHandler);
					drawer.off('click', drawerClick);
					drawer.remove();
					watcher();
				});
			}
		}
(6521,3,6528,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl, linker) {
			const slider = angular.element(template);
			linker(scope, (copy, scope) => {
				slider.append(copy);
				const content = $compile(slider)(scope);
				$timeout(() => element.replaceWith(content));
			});
		}
(6745,3,6749,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl, linker) {
			linker(scope, (copy) => element.append(copy));
			const content = $compile(template)(scope);
			element.replaceWith(content);
		}
(6848,3,6882,5): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl, linker) {

			if (attributes.auto === 'true') {
				scope.sliderOptions.buttons = false;
				scope.sliderPlugins.push(EmblaCarouselAutoScroll({
					speed: 0.5,
					startDelay: 100,
					stopOnMouseEnter: false,
					stopOnInteraction: false,
				}));
			}

			const content = $compile(sliderTemplate)(scope);
			$timeout(() => element.replaceWith(content));

			const request = $requestBuilders.$webproductListRequestBuilder();
			if (attributes.sort) request.setSort(attributes.sort);
			if (attributes.query) request.parseQuery(attributes.query);
			if (attributes.category) request.addCategory(attributes.category);
			request.addParameter('pageSize', attributes.size ? attributes.size : 10);
			request.addParameter('pageIndex', attributes.page ? attributes.page : 1);

			const render = (request) => {
				$api.$webproduct.list(request.make()).then((result) => {
					if (result.value) return result.value.products
					else throw 'Products Not Found';
				}).then((data) => {
					scope.products = data.map((item) => ({
						...item,
						image: `/cdn-bedrosian/assets/products/hiresimages/${item.imageName}`,
						altImage: item.alternativeImageUrl ? item.alternativeImageUrl.replace(/(http:|https:|)\/\/res(-\d*)?\./g, 'https://res.').replace(/\/t_[^/]+/g, '') : null,
						href: $settings.getSecureUrl(`product/detail/${item.urlFriendlyStyleName ? item.urlFriendlyStyleName : ''}?itemNo=${item.productCode}`, true),
					}));
				})
			}
(6894,3,6896,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attribute, ctrl) {
			ctrl.addItem(attribute.itemNo);
		}
(6929,3,6933,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attribute, ctrl, linker) {
			const content = $compile(template)(scope);
			$timeout(() => element.replaceWith(content));
			linker(scope, (copy) => element.append(copy));
		}
(6938,3,6943,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl) {
			ctrl.addItem({
				image: attributes.image,
				href: settings.getSecureUrl(`product/detail/?itemNo=${attributes.itemNo}&sample=true`, true),
			});
		}
(7004,3,7025,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, $ctrl, linker) {
			scope.header = attributes.header;

			const root = $compile(template)(scope);
			$timeout(() => element.replaceWith(root), 0);

			scope.$watchCollection('items', (value) => {
				if (!value || !value.length) return;
				scope.selected = value[0].value;
			});

			scope.$watch('selected', (value) => {
				if (!value || !scope.items || !scope.items.length) return;
				const item = scope.items.find(x => x.value === value);
				item.linker(item.inner, (copy) => {
					const container = root.find('[role="region"]');
					container.empty().append(copy);
				});
			});

			linker(scope, (copy) => element.append(copy));
		}
(7032,3,7040,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl, linker) {
			const item = {
				disabled: attributes.disabled,
				value: attributes.value,
				linker: linker,
				inner: scope,
			};
			ctrl.addItem(item);
		}
(7237,4,7247,5): run-time error JS1314: Implicit property name must be identifier: compile(element) {
				const name = element.data('name');
				const key = `icon-${name}`;
				if (name && injector.has(key)) {
					let svg = injector.get(key);
					let icon = angular.element(svg);
					element.append(icon);
				} else {
					element.remove();
				}
			}
(7287,4,7318,6): run-time error JS1314: Implicit property name must be identifier: controller($scope, $attrs) {
				$scope.src = ($parse($attrs.image))($scope) || ($parse($attrs.$attr.image))($attrs);
				$scope.sizes = ($parse($attrs.sizes))($scope) || ($parse($attrs.$attr.sizes))($attrs);
				$scope.width = ($parse($attrs.width))($scope) || ($parse($attrs.$attr.width))($attrs);
				$scope.height = ($parse($attrs.height))($scope) || ($parse($attrs.$attr.height))($attrs);
				$scope.products = ($parse($attrs.products))($scope) || ($parse($attrs.$attr.products))($attrs);

				$scope.toggleProducts = function ($event) {
					$event.preventDefault();
					$event.stopPropagation();
					$scope.active = !$scope.active;
				};

				if (!/[https?]*:?\/\/.*$/.test($scope.src)) {
					let {groups: {collection, src}} = $scope.src.match(/(?<collection>[^-]+)-(?<src>[^\s]+)$/);
					if (collection && src) $scope.src = `installation_shots/${collection}/${src.replace(/-/g, '_')}`;
				}

				if (!$scope.products) {
					let reg = /(installation_shots)\/(?<collection>.+)\/(?<src>.+)$/;
					if (!reg.test($scope.src)) return;
					let {groups: {collection, src}} = $scope.src.match(reg);
					let imageId = `${decodeURI(collection)}-${src}`.replace(/[\s|\_]/g, '-').toLowerCase();
					$api.$gallery.detail(imageId).then(res => {
						if (!res.value) return;
						$scope.src = res.value.largeImageSrc.replace(/(http:|https:|)\/\/res(-\d*)?\./g, 'https://res.').replace(/\/t_[^/]+/g, '');
						$scope.products = res.value.products.map(product => ({
							...product,
							href: appSettings.getSecureUrl(`product/detail/?itemNo=${product.code}`, true)
						}));
					});
				}
(7491,3,7564,4): run-time error JS1314: Implicit property name must be identifier: compile(element, attrs) {
			return function (scope) {
				scope.currentItem = null;

				const children = element.children();
				element.replaceWith($compile(children)(scope));

				const elementClass = attrs.class;
				children.addClass(elementClass);

				const body = angular.element('body');

				const debouncedOpen = _.debounce((event, item) => {
					$timeout(() => {
						scope.$apply(() => {
							if (!item.hasChild) return;

							const target = event.currentTarget;
							const top = target.offsetTop + target.offsetHeight;
							const height = window.outerHeight - top

							const childScope = scope.$new(true);
							childScope.menu = item.children;

							const element = $compile(megaTemplate)(childScope);
							element.css({top, height});
							body.append(element);

							scope.currentItem = {
								scope: childScope,
								element,
								item,
							};
						})
					})
				}, 300);

				scope.open = function (event, item) {
					if (scope.currentItem && scope.currentItem.item === item) return;
					close().then(() => debouncedOpen(event, item));
				};

				const close = () => new Promise((resolve) => {
					debouncedOpen.cancel();
					if (!scope.currentItem) return resolve();
					scope.currentItem.element.addClass('bd-menu-large-mega-out');
					scope.currentItem.element.removeClass('bd-menu-large-mega-in');
					$timeout(() => {
						if (!scope.currentItem) return resolve();
						scope.currentItem.scope.$destroy();
						scope.currentItem.element.remove();
						scope.currentItem = null;
						return resolve();
					}, 300);
				});

				const debouncedClose = _.debounce(close, 500);

				angular.element(document).on('mouseover', function (event) {
					debouncedClose.cancel();

					const target = angular.element(event.target)[0];
					const isOverMainMenu = children[0].contains(target);
					const isOverSubMenu = scope.currentItem
						&& scope.currentItem.element[0] !== target
						&& scope.currentItem.element[0].contains(target);

					if (!isOverMainMenu && !isOverSubMenu) scope.$apply(() => {
						debouncedOpen.cancel();
						debouncedClose()
					});
				});
			};
		}
(7647,3,7735,4): run-time error JS1314: Implicit property name must be identifier: compile(element, attrs) {
			return function (scope) {
				scope.active = false;

				const items = [];

				const children = element.children();
				element.replaceWith($compile(children)(scope));

				const elementClass = attrs.class;
				children.addClass(elementClass);

				scope.open = () => scope.active = true;

				scope.onItemClick = (item) => {
					if (item.url && !item.hasChild) {
						window.location = item.url;
						scope.active = false;
						return;
					}
					const childScope = scope.$new(false);
					childScope.data = {
						item,
						menu: item.children,
						header: items.map(item => item.item.title).join(' / '),
					};
					const content = ($compile(menuContentTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
						item,
					});
				}

				scope.onLocationsMenuClick = () => {
					const childScope = scope.$new(false);
					childScope.data = {
						locations: scope.locations,
						currentLocation: 'California',
					};
					const content = ($compile(menuLocationsTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
					});
				}

				scope.onLocationItemClick = (item) => {
					scope.data = {busy: true};
					branchLocatorService.ChooseStateByAbbreviation(item.Abbreviation)
						.then(() => window.location.reload())
						.then(() => scope.active = false);
				};

				scope.onAccountMenuClick = () => {
					const childScope = scope.$new(false);
					childScope.data = {menu: scope.accountMenu};
					const content = ($compile(menuAccountTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
					});
				}

				scope.back = () => {
					const item = items.pop();
					item.page.addClass('bd-menu-small-content-out');
					item.page.removeClass('bd-menu-small-content-in');
					$timeout(() => {
						item.scope.$destroy();
						item.page.remove();
					}, 299);
				}

				scope.onDrawerClose = () => {
					while (items.length > 0) {
						const item = items.pop();
						item.scope.$destroy();
						item.page.remove();
					}
				};
			}
		}
(7800,3,7839,4): run-time error JS1314: Implicit property name must be identifier: compile(element, attrs, linker) {
			let zone = attrs.zone;
			let row = parseInt(attrs.row) || 3;
			return (scope) => {
				let inner = scope.$new(false);
				let root = angular.element('<div class="bd-product-list-banner"></div>');

				let breakpoints = [
					{
						count: 4,
						media: '(min-width: 1920px)',
					},
					{
						count: 4,
						media: '(min-width: 768px)',
					},
					{
						count: 2,
						media: '(max-width: 768px)',
					},
				];

				const update = () => {
					let counter = breakpoints.find(x => window.matchMedia(x.media).matches);
					let order = (counter) ? counter.count * (row - 1) : 3;
					root.css('order', order);
				}

				update();

				return linker(inner, (clone) => {
					const hasContent = Array.from(clone).some(x => x.nodeType !== Node.TEXT_NODE);
					if (hasContent) {
						root.append(clone);
						element.replaceWith(root);
						angular.element(window).on('resize', update);
					} else element.remove();
				});
			}
		}
(7907,3,7913,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes, ctrl, linker) {
			linker(scope, (copy, scope) => {
				element.append(copy);
				const slider = $compile(template)(scope);
				$timeout(() => element.replaceWith(slider));
			});
		}
(7919,3,7925,4): run-time error JS1314: Implicit property name must be identifier: link(scope, elem, attr, ctrl) {
			ctrl.addItem({
				label: attr.label,
				image: attr.image,
				href: attr.href,
			});
		}
(7951,3,7963,4): run-time error JS1314: Implicit property name must be identifier: controller($scope) {
			return $scope.$watchCollection('itemsNo', (value) => {
				if (!value || value[0] === null || value.length === 0) return;
				service.getItems(value, $scope.relationType).then((result) => {
					$timeout(() => {
						$scope.$apply(() => {
							$scope.useSkeleton = false;
							$scope.items = result
						});
					});
				});
			});
		}
(8059,3,8081,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes) {
			scope.show = false;

			scope.select = (option) => scope.ngModel = option.value;

			scope.$watch('ngModel', (value) => scope.selected = value);

			element.on('click', () => {
				scope.show = !scope.show;
				scope.$digest();
			});

			angular.element(document).on('scroll', () => {
				scope.show = false;
				scope.$digest();
			});

			angular.element(document).on('click', (event) => {
				if (element[0].contains(event.target)) return;
				scope.show = false;
				scope.$digest();
			});
		}
(8168,4,8214,6): run-time error JS1314: Implicit property name must be identifier: compile(element, attr, linker) {
				return (scope, element) => {
					scope.rootClass = attr.rootClass;
					scope.containerClass = attr.containerClass;
					let root = $compile('<div class="bd-slider-up-root" ng-class="rootClass"></div>')(scope);
					let container = $compile(`<div class="bd-slider-up-container" ng-class="containerClass"></div>`)(scope);
					return linker(scope, (clone, scope) => {
						element.prepend(root);
						root.append(container);
						container.append(clone);
						return $timeout((() => {
							let options = ($parse(attr.options))(scope);
							let plugins = ($parse(attr.plugins))(scope);

							scope.sliderOptions = {...options, container: container.get(0)};
							if (scope.sliderOptions.dots === undefined) scope.sliderOptions.dots = true;
							if (scope.sliderOptions.buttons === undefined) scope.sliderOptions.buttons = true;
							scope.slider = new EmblaCarousel(root.get(0), scope.sliderOptions, plugins);

							scope.slider.on('init', () => {
								$timeout(() => {
									scope.dots = scope.slider.scrollSnapList();
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});

							scope.slider.on('reInit', () => {
								$timeout(() => {
									scope.dots = scope.slider.scrollSnapList();
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});

							scope.slider.on('select', () => {
								$timeout(() => {
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});
						}), 0);
					});
				}
(8556,3,8563,4): run-time error JS1314: Implicit property name must be identifier: compile(elem, attr, linker) {
			return (scope) => {
				return linker(scope, (copy) => {
					angular.element(attr.to).append(copy);
					elem.remove();
				})
			}
		}
(8570,3,8573,4): run-time error JS1314: Implicit property name must be identifier: link(scope, element, attributes) {
			const tag = $compile(`<script src="https://widget.trustmary.com/${attributes.key}"></script>`)(scope);
			element.replaceWith(tag);
		}
(11503,3,11516,4): run-time error JS1314: Implicit property name must be identifier: open(code) {
			const scope = $scope.$new(true);
			
			scope.code = code;
			scope.current = {Product: $scope.$model.products.find(x => x.ProductCode === code)};
			
			$dialog.open({
				scope,
				showClose: false,
				template: 'quick-add.html',
				controller: 'QuickAddController',
				className: 'ngdialog-theme-plain ngdialog-quick-add',
			});
		}
(10559,80-86): run-time error JS1018: 'return' statement outside of function: return
(5053,3-11): run-time error JS1018: 'return' statement outside of function: return {
(4326,6-13): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: banners
 */
(function () {
	'use strict';

	function appUtils() {
		return {
			round: round
		};

		function round(value, precision) {
			precision = (typeof precision !== 'undefined') ? precision : 2;
			var multiplier = Math.pow(10, precision);
			return Math.round(value * multiplier) / multiplier;
		}
	}

	angular.module('app.utils', []).factory('appUtils', appUtils);

}());
;
(function () {
	'use strict';

	angular
    .module('ngGeolocation', [])
    .factory('$geolocation', ['$rootScope', '$window', '$q', function ($rootScope, $window, $q) {

    	function supported() {
    		return 'geolocation' in $window.navigator;
    	}

    	var retVal = {
    		getCurrentPosition: function (options) {
    			var deferred = $q.defer();
    			if (supported()) {
    				$window.navigator.geolocation.getCurrentPosition(
                        function (position) {
                        	$rootScope.$apply(function () {
                        		retVal.position.coords = position.coords;
                        		retVal.position.timestamp = position.timestamp;
                        		deferred.resolve(position);
                        	});
                        },
                        function (error) {
                        	$rootScope.$apply(function () {
                        		deferred.reject({ error: error });
                        	});
                        }, options);
    			} else {
    				deferred.reject({
    					error: {
    						code: 2,
    						message: 'This web browser does not support HTML5 Geolocation'
    					}
    				});
    			}
    			return deferred.promise;
    		},

    		watchPosition: function (options) {
    			if (supported()) {
    				if (!this.watchId) {
    					this.watchId = $window.navigator.geolocation.watchPosition(
                            function (position) {
                            	$rootScope.$apply(function () {
                            		retVal.position.coords = position.coords;
                            		retVal.position.timestamp = position.timestamp;
                            		delete retVal.position.error;
                            		$rootScope.$broadcast('$geolocation.position.changed', position);
                            	});
                            },
                            function (error) {
                            	$rootScope.$apply(function () {
                            		retVal.position.error = error;
                            		delete retVal.position.coords;
                            		delete retVal.position.timestamp;
                            		$rootScope.$broadcast('$geolocation.position.error', error);
                            	});
                            }, options);
    				}
    			} else {
    				retVal.position = {
    					error: {
    						code: 2,
    						message: 'This web browser does not support HTML5 Geolocation'
    					}
    				};
    			}
    		},

    		clearWatch: function () {
    			if (this.watchId) {
    				$window.navigator.geolocation.clearWatch(this.watchId);
    				delete this.watchId;
    			}
    		},

    		position: {}
    	};

    	return retVal;
    }]);
}());;
(function () {

	"use strict";

	/*
	  Use UomConverter in order to perform any uom conversions
	*/
	function uomConverter(appUtils) {

		var maxPrecision = 28;

		function getQtyPer1Base(baseRatio) {
			return appUtils.round(1 / baseRatio, 4);
		}

		function toBaseUom(value, fromUom, precision) {
			precision = (typeof precision !== 'undefined') ? precision : 0;
			if (value && fromUom && fromUom.BaseRatio > 0) {
				var baseQty = fromUom.IsFractional ? Big(value).div(Big(getQtyPer1Base(fromUom.BaseRatio))) : value * fromUom.BaseRatio;
				return precision > 0 ? appUtils.round(baseQty, precision) : Math.ceil(baseQty);
			}
			return 0;
		}

		function fromBaseUom(value, toUom, precision) {
			precision = (typeof precision !== 'undefined') ? precision : 2;
			if (value && toUom && toUom.BaseRatio > 0) {
				var qty = toUom.IsFractional ? value * getQtyPer1Base(toUom.BaseRatio) : value / toUom.BaseRatio;
				return appUtils.round(qty, precision);
			}
			return 0;
		}

		function toUom(value, fromUom, toUom) {
			if (!value) {
				return 0;
			}

			if (fromUom.Id === toUom.Id) {
				return value;
			}

			if (fromUom && fromUom.BaseRatio > 0 && toUom && toUom.BaseRatio > 0) {
				if (fromUom.BaseRatio === 1) {
					return fromBaseUom(value, toUom, 4);
				}
				if (toUom.BaseRatio === 1) {
					return toBaseUom(value, fromUom);
				}
				var preciseBaseUomValue = toBaseUom(value, fromUom, maxPrecision);
				return fromBaseUom(toUom.IsFractional ? preciseBaseUomValue : Math.ceil(preciseBaseUomValue), toUom, 4);
			}
		}

		return {
			toBaseUom: toBaseUom,
			fromBaseUom: fromBaseUom,
			toUom: toUom
		}
	}

	angular.module('app.utils').service('uomConverter', ['appUtils', uomConverter]);

})();
;
(function () {
	'use strict';

	angular.module('app.utils')
		.factory('appSettings', ['$window', '$filter', appSettings]);

	function appSettings($window, $filter) {
		var cachedRoot = null;
		var cachedContentRoot = null;
		var cachedLanguage = null;
		var cachedSecureRoot = null;

		return {
			getUrl: getUrl,
			getSecureUrl: getSecureUrl,
			getContentPath: getContentPathFromHtmlRoot,
			getImagePath: getImagePath,
			getBaseUrl: getBaseUrl,
			getCurrentUrl: getCurrentUrl,
			getSortedArray: getSortedArray
		}

		// return base url
		function getBaseUrl() {
			var baseUrl = getUrl('', true).replace(/\/$/, '');
			return baseUrl;
		}

		// return current url
		function getCurrentUrl() {
			var currentUrl = $window.location.pathname.replace(/\/$/, '');
			return currentUrl;
		}
		
		function getLanguageFromHtmlRoot() {
			if (cachedLanguage) {
				return cachedLanguage;
			}

			cachedLanguage = $('html').data('language');
			return cachedLanguage;
		}

		function getSecureUrl(relativeUrl, includeLanguage) {
			function getSecureRootPathFromHtmlRoot() {
				if (cachedSecureRoot) {
					return cachedSecureRoot;
				}

				cachedSecureRoot = $('html').data('secure-root');
				return cachedSecureRoot;
			}

			var secureRoot = getSecureRootPathFromHtmlRoot();

			if (includeLanguage) {
				var language = getLanguageFromHtmlRoot();
				secureRoot += language + "/";
			}

			var result = secureRoot + relativeUrl;
			return result;
		}

		//	Note: relativeUrl must not include leading '/'
		function getUrl(relativeUrl, includeLanguage) {
			function getRootPathFromHtmlRoot() {
				if (cachedRoot) {
					return cachedRoot;
				}

				cachedRoot = $('html').data('root');
				return cachedRoot;
			}

			var rootUrl = getRootPathFromHtmlRoot();

			if (includeLanguage) {
				var language = getLanguageFromHtmlRoot();
				rootUrl += language + "/";
			}

			var result = rootUrl + relativeUrl;

			return result;
		}

		function getContentPathFromHtmlRoot() {
			if (cachedContentRoot) {
				return cachedContentRoot;
			}

			cachedContentRoot = $('html').data('content-root');
			return cachedContentRoot;
		}

		function getSortedArray(array, sortField) {
			return $filter('orderBy')(array, sortField);
		}

		//	Note: imageName must not include leading '/'
		function getImagePath(imageName) {
			var contentPath = getContentPathFromHtmlRoot();
			var result = contentPath + 'images/' + imageName;
			return result;
		}

	}
}());;
(function () {
	'use strict';
	
	angular.module('app.utils')
		.factory('spinner', spinner);
	
	function spinner() {
		NProgress.configure({showSpinner: false});
		
		return {
			startLoad: startLoad,
			progress: progress,
			endLoad: endLoad
		}
		
		/*
		 * Start showing spinner indicator
		 */
		function startLoad() {
			NProgress.start();
		}
		
		/*
		 * Indicate some progress during long-time job.
		 * @param {Number} percent should be 0 < percent < 1.
		 */
		function progress(percent) {
			NProgress.inc(percent);
		}
		
		/*
		 * Finish showing spinner indicator
		 */
		function endLoad() {
			NProgress.done();
		}
	}
}());;
(function () {
	'use strict';

	const httpErrorsHandler = (state, $injector) => {
		let $q = $injector.get('$q');
		if (!state) return $q.reject(state);
		if (state.status === 401) {
			let $http = $injector.get('$http');
			return $http(state.config);
		}
		return $q.reject(state);
	}

	window.bdApp = angular.module('app', [
		'ngTouch',
		'ngDialog',
		'app.utils',
		// 'ngAnimate',
		'ngCookies',
		'ngSanitize',
		'ngMessages',
		'ui.carousel',
		'hmTouchEvents',
		'ngGeolocation',
		'angular-inview',
		'app.storelocator',
		'720kb.socialshare',
		'angular-flexslider',
	]);

	window.bdApp.config(function ($sceDelegateProvider) {
		$sceDelegateProvider.resourceUrlWhitelist([
			'self',
			'http://*.cloudinary.com/**',
			'https://*.cloudinary.com/**',
		]);
	});

	window.bdApp.config(function ($httpProvider) {
		$httpProvider.interceptors.push(function ($q, $injector) {
			return {
				request: function (config) {
					config.headers.StoreFrontPublicKey = window.StoreFrontPublicKey;
					if (config.url.includes('refreshtokens')) return config;
					let $apiTokenService = $injector.get('$apiTokenService');
					return $apiTokenService.getToken().then(token => {
						if (token) config.headers.Authorization = `Bearer ${token}`;
						return config;
					});
				},
				responseError: (state) => httpErrorsHandler(state, $injector),
			}
		});
	});

	const buildversion = angular.element('html').data('version');

	window.bdApp.value('buildversion', buildversion);

	window.bdApp.constant('myModuleConst', {
		salesRoleName: 'Sales',
		oepTagTemplatePath: 'scripts/app/tags/oepTagTemplate.html' + `?v=${buildversion}`,
		avatarTemplate: 'scripts/app/account/directives/avatar.html' + `?v=${buildversion}`,
		partialUserTagsPath: 'scripts/app/tags/UserTagsModalDialog.html' + `?v=${buildversion}`,
		shareButtonsPath: 'scripts/app/common/directives/shareButtons.html' + `?v=${buildversion}`,
		oepSearchPanel: 'scripts/app/common/directives/oepSearchPanel.html' + `?v=${buildversion}`,
		searchBoxTemplatePath: 'scripts/app/common/directives/oepSearch.html' + `?v=${buildversion}`,
		tearsheetTemplatePath: 'scripts/app/product/directives/oepTearsheet.html' + `?v=${buildversion}`,
		oepFilterTemplate: 'scripts/app/common/directives/oepFilterTemplate.html' + `?v=${buildversion}`,
		customerUserEditTemplate: 'scripts/app/customer-users/templates/edit.html' + `?v=${buildversion}`,
		loadWebContentTemplate: 'scripts/app/common/directives/loadWebContent.html' + `?v=${buildversion}`,
		subscribeModalTemplatePath: 'scripts/app/signup/SubscribeModalTemplate.html' + `?v=${buildversion}`,
		oepSignUpEmailTemplatePath: 'scripts/app/signup/oepSignUpEmailTemplate.html' + `?v=${buildversion}`,
		customerUsersListTemplate: 'scripts/app/customer-users/templates/index.html' + `?v=${buildversion}`,
		searchAutocompleteTemplatePath: 'scripts/app/common/directives/oepSearchAutocomplete.html' + `?v=${buildversion}`,
		searchWithSuggestionsTemplatePath: 'scripts/app/common/directives/oepSearchWithSuggestions.html' + `?v=${buildversion}`,
		notificationPreferenceTemplate: 'scripts/app/notification-preference/notification-preference.html' + `?v=${buildversion}`,
		searchWithSuggestionsMobileTemplatePath: 'scripts/app/common/directives/oepSearchWithSuggestionsMobile.html' + `?v=${buildversion}`,
	});
})();
;
(function () {
	"use strict";
	
	angular.module('app').controller('AccountMenuCtrl', ["$scope", function ($scope) {
		$scope.active = false;
		
		$scope.toggleMenu = () => {
			$scope.active = !$scope.active;
			$('body, html').css('overflow', $scope.active ? 'clip' : '');
		}
	}]);
})()
;
(function () {
	'use strict';

	function BusinessAddressCtrl($scope, $http, $window, appSettings, branches, addresses, states) {
		$scope.model = {
			isBusy: false,
			selectedCustomerBranch: ''
		};

		$scope.states = states;
		$scope.addresses = addresses;
		$scope.branches = branches;

		$scope.errors = [];
		$scope.data = {};

		$scope.setDetault = setDetault;
		$scope.addAddress = addAddress;
		$scope.editAddress = editAddress;
		$scope.deleteAddress = deleteAddress;
		$scope.load = load;
		$scope.setCustomerBranch = setCustomerBranch;

		function load(customerBranchId) {
			$http.post(appSettings.getSecureUrl('AddressBook/Shipping/Business', true), {
				customerBranchId: customerBranchId
			}).then(function (response) {
				$scope.addresses = response.data.addresses;
				$scope.model.isBusy = false;
			}, function (error) {
				$scope.model.isBusy = false;
				console.log(error);
			});
		}

		function setCustomerBranch() {
			load($scope.model.selectedCustomerBranch);
			//$scope.model.isBusy = true;
			//$window.location.href = appSettings.getSecureUrl('AddressBook/Shipping/Business/', true) + "?customerBranchId=" + encodeURIComponent(customerBranchId);
		}

		function setDetault(address) {
			$http.post(appSettings.getSecureUrl('AddressBook/Shipping/BusinessAddressSetDefault', true), {
				shipToAddressId: address.shipToAddressId,
				customerBranchId: address.customerId,
			}).then(function (response) {

				if (response.data.success) {
					$scope.data.errors = null;
					$scope.data.confirm = true;
				} else {
					$scope.data.errors = response.data.errors;
				}
				$scope.model.isBusy = false;

				$scope.load($scope.model.selectedCustomerBranch);

			}, function (error) {
				$scope.model.isBusy = false;
				console.log(error);
			});
		}

		function addAddress(customerBranchId) {
			$scope.model.isBusy = true;
			$window.location.href = appSettings.getSecureUrl('AddressBook/Shipping/BusinessAddressEdit/', true) + "?customerBranchId=" + encodeURIComponent(customerBranchId);
		}

		function editAddress(address) {
			$scope.model.isBusy = true;
			$window.location.href = appSettings.getSecureUrl('AddressBook/Shipping/BusinessAddressEdit/', true) + "" + encodeURIComponent(address.shipToAddressId) + "?customerBranchId=" + encodeURIComponent(address.customerId);
		}

		function deleteAddress(address) {
			if (confirm('Are you sure that you want to remove this entry?')) {
				$http.post(appSettings.getSecureUrl('AddressBook/Shipping/BusinessAddressDelete', true), {
					shipToAddressId: address.shipToAddressId,
					customerBranchId: address.customerId
				}).then(function (response) {
					$scope.model.isBusy = false;
				}, function (error) {
					$scope.model.isBusy = false;
					console.log(error);
				});
			}
		}
	};

	angular
		.module('app')
		.controller('BusinessAddressCtrl', ['$scope', '$http', '$window', 'appSettings', 'branches', 'addresses', 'states', BusinessAddressCtrl]);
})();
;
(function () {
	'use strict';

	function BusinessFormCtrl($scope, $http, $window, spinner, appSettings, states) {
		$scope.model = {
			address: {},
			billingAddress: {},
			date: new Date(),
			hasServerError: false
		};

		$scope.states = states;

		$scope.customerTypes = [
			{ name: "Dealer" },
			{ name: "Distributor" },
            { name: "Designer" },
			{ name: "Design Center" },
			{ name: "Fabricator" },
			{ name: "Pool Contractor" },
            { name: "Other" },
			{ name: "General Contractor" },
			{ name: "Home/Box Store" },
			{ name: "Landscape" },
			{ name: "Online Retailer" },
			{ name: "Tile Specialty" },
			{ name: "Property Manager" }
		];

		$scope.model.customerType = $scope.customerTypes[0].name;

		$scope.oafDefaultTypes = [
			{ name: "Box" },
			{ name: "Commercial" },
			{ name: "Dist" },
			{ name: "Retail" },
			{ name: "Tract" }
		];

		$scope.model.oafType = $scope.oafDefaultTypes[0].name;

		$scope.sendForm = function () {

			if ($scope.business.$invalid) {
				return;
			}

			spinner.startLoad();
			$scope.busy = true;

			$scope.model.billingArrdessSameAsPhysical = false;
			var data = JSON.stringify($scope.model);
			var url = appSettings.getUrl('account/CustomerRequest', true);
			$http.post(url, { 'request': data })
				.then(function (response) {
					if (response.data.success) {
						$window.location.href = appSettings.getUrl('account/complete/customerrequested', true);
					} else {
						handleSendFormErorr();
					}
				}, function (error) {
					handleSendFormErorr();
				});
		}

		function handleSendFormErorr() {
			$scope.model.hasServerError = true;
			spinner.endLoad();
			$scope.busy = false;
		}
	};

	var app = angular
		.module('app')
		.controller('BusinessFormCtrl', ['$scope', '$http', '$window', 'spinner', 'appSettings', 'states', BusinessFormCtrl]);
})();;
(function () {
	'use strict';

	function CustomerBalanceController($scope, $http, CustomerBalanceService) {

		$scope.balance = {
			balance: "",
			customerNo: "",
			paymentTerm: "",
			availableCredit: ""
		};

		$scope.showBalance = false;

		$scope.loadingCustomerBalance = true;

		CustomerBalanceService.getBalance().then(function (result) {
			$scope.balance = result;
			$scope.showBalance = true;
		}, function (error) {
			console.log(error);
		}).finally(function () {
			$scope.loadingCustomerBalance = false;
		});
	}

	angular
		.module('app')
		.controller('CustomerBalanceController', ['$scope', '$http', 'CustomerBalanceService', CustomerBalanceController]);
})();
;
(function () {
	'use strict';
	
	function CustomerBalanceService(appSettings, $http, $q, $cookies, $api) {
		
		function getBalance() {
			let def = $q.defer();
			$api.$customer.getbalance().then(
				(res) => (res.value) ? def.resolve(res.value) : def.reject("Failed to get invoices!"),
				() => def.reject("An error occurred while sending your enquiry. Please try again or contact an administrator.")
			);
			return def.promise;
		}
		
		return {
			getBalance: getBalance
		}
	}
	
	window.bdApp.service('CustomerBalanceService', ['appSettings', '$http', '$q', '$cookies', '$api', CustomerBalanceService]);
})();
;
(function () {
	'use strict';

	function PhoneInputDirective($filter, $browser) {
		return {
			require: 'ngModel',
			link: function ($scope, $element, $attrs, ngModelCtrl) {
				var listener = function () {
					var value = $element.val().replace(/[^0-9]/g, '');
					$element.val($filter('tel')(value, false));
				};

				ngModelCtrl.$parsers.push(function (viewValue) {
					return viewValue.replace(/[^0-9]/g, '').slice(0, 10);
				});

				ngModelCtrl.$render = function () {
					$element.val($filter('tel')(ngModelCtrl.$viewValue, false));
				};

				$element.bind('change', listener);
				$element.bind('keydown', function (event) {
					var key = event.keyCode;
					if (key == 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) {
						return;
					}
					$browser.defer(listener);
				});

				$element.bind('paste cut', function () {
					$browser.defer(listener);
				});
			}

		};
	}

	angular.module('app').directive('phoneInput', ['$filter', '$browser', PhoneInputDirective]);
})();
;
(function () {
	'use strict';

	function SignUpFormCtrl($scope, $element) {
		$scope.model = {
			zip: null,
			email: null,
			password: null,
			lastName: null,
			firstName: null,
			oldPassword: null,
			confirmEmail: null,
			customerType: null,
			confirmPassword: null,
			hidRecaptchaToken: null,
		};

		$scope.formSubmit = function (event, action) {
			event.preventDefault();

			if ($scope.registerForm.$invalid) return;

			let sitekey = $element.data('sitekey');

			if (sitekey && grecaptcha) grecaptcha.ready(() => {
				grecaptcha.execute(sitekey, {action}).then((token) => {
					$scope.model.hidRecaptchaToken = token;
					setTimeout(() => {
						$scope.$digest();
						if ($scope.registerForm.$valid) event.target.submit();
					}, 0);
				});
			});
		}
	}

	window.bdApp.controller('SignUpFormCtrl', ['$scope', '$element', SignUpFormCtrl]);
})();
;
(function() {
	function TelFilter() {
		return function(tel) {
			if (!tel) {
				return '';
			}

			var value = tel.toString().trim().replace(/^\+/, '');

			if (value.match(/[^0-9]/)) {
				return tel;
			}

			var country, city, number;

			switch (value.length) {
			case 1:
			case 2:
			case 3:
				city = value;
				break;

			default:
				city = value.slice(0, 3);
				number = value.slice(3);
			}

			if (number) {
				if (number.length > 3) {
					number = number.slice(0, 3) + '-' + number.slice(3, 7);
				} else {
					number = number;
				}

				return ("(" + city + ") " + number).trim();
			} else {
				return "(" + city;
			}

		};
	}

	angular.module('app').filter('tel', [TelFilter]);
})();;
(function () {

	'use strict';

	angular
		.module('app')
		.controller('WelcomeDialogCtrl', WelcomeDialogCtrl);

	WelcomeDialogCtrl.$inject = ['$scope', '$http', '$window', 'appSettings', 'spinner', 'ngDialog'];

	function WelcomeDialogCtrl($scope, $http, $window, appSettings, spinner, ngDialog) {
		ngDialog.open({
			template: '/welcome-dialog.html',
			className: 'ngdialog-theme-plain welcome-dialog',
			controller: this,
			scope: $scope
		});
	}
})();;
(function () {
	'use strict';

	angular.module('app')
		.directive('avatar', ['appSettings', 'myModuleConst', 'spinner', function (appSettings, myModuleConst, spinner) {
			return {
				restrict: 'E',
				templateUrl: appSettings.getUrl(myModuleConst.avatarTemplate, false),
				scope: {
					avatarUrl: '=avatarUrl',
					userName: '=userName'
				},
				link: function (scope, element, attrs) {
					scope.changeAvatarUrl = appSettings.getUrl("en/account/changeAvatar");

					$(element).find("#avatarImg").click(function () {
						$(element).find("#avatarFile").click();
					});

					$(element).find("#avatarFile").change(function () {
						spinner.startLoad();
						this.form.submit();
					});
				}
			};
		}]);
}());
;
(function () {
    'use strict';

    window.bdApp.directive('refValidator', () => ({
        require: 'ngModel',
        link: (scope, elem, attrs, ctrl) => {
            const ref = attrs.refValidator

            const unwatch = scope.$watch(ref, () => ctrl.$validate());
            scope.$on('$destroy', unwatch);

            ctrl.$validators.equals = (value) => {
                const refValue = _.get(scope, ref);
                return !value || value === '' || value === refValue;
            }
        }
    }))
})()
;
(function () {
	'use strict';
	window.bdApp.controller('AddressController', ($api, $http, $scope, $timeout) => {
		$scope.data = {};
		$scope.address = {};
		
		$scope.$watch('address.Country', (value) => {
			if (!value) return
			$api.$storefront.getstateprovinces(value).then((res) => $scope.data.states = res.value)
		});
		
		$scope.$watch('address.StateProvince', (value) => {
			if (typeof value !== 'string' || !$scope.data.states) return;
			$scope.address.StateProvince = $scope.data.states.find(x => x.id === value);
		});
		
		$scope.$watch('data.states', (value) => {
			if (!value || typeof $scope.address.StateProvince !== 'string') return;
			$scope.address.StateProvince = value.find(x => x.id === $scope.address.StateProvince);
		});
		
		$scope.autocomplete = (component) => {
			let place = component.getPlace();
			place.address_components.map(component => {
				switch (component.types[0]) {
					case "street_number": {
						$scope.address.AddressLine1 = component.long_name;
						break;
					}
					case "route": {
						$scope.address.AddressLine1 = `${$scope.address.AddressLine1} ${component.long_name}`;
						break;
					}
					case "locality": {
						$scope.address.City = component.long_name;
						break;
					}
					case "administrative_area_level_1": {
						$scope.address.StateProvince = component.short_name;
						break;
					}
					case "postal_code": {
						$scope.address.PostalCode = component.long_name;
						break;
					}
				}
			});
			$timeout(() => $scope.$digest());
		}
	});
})();
(function () {
	'use strict';
	
	function CheckoutCtrl($scope, $injector, $element, $timeout, $http, $location, $window, $anchorScroll, ngDialog, spinner, appSettings, shoppingBagId, uiGmapGoogleMapApi) {
		$scope.data = {};
		$scope.model = {};
		
		$scope.refreshCheckoutItems = refreshCheckoutItems;
		$scope.initCitizenPayFlowSdk = initCitizenPayFlowSdk;
		$scope.initCitizenPayFlowPopup = initCitizenPayFlowPopup;
		$scope.initCitizenPayFlowSameTab = initCitizenPayFlowSameTab;
		
		$scope.busy = false;
		
		let forms = $element.find('form');
		forms.map((_, el) => el.addEventListener('submit', () => $timeout(() => $scope.busy = true)));
		
		function refreshCheckoutItems() {
			var url = appSettings.getUrl('shoppingbag/checkoutitems/', true);
			
			if (shoppingBagId) {
				url += '?ShoppingBagQuoteId=' + shoppingBagId;
			}
			
			var req = {
				method: 'GET',
				url: url,
				headers: {
					'X-Requested-With': 'XMLHttpRequest'
				}
			};
			
			$http(req).then(function successCallback(response) {
				
				$scope.data.model = response.data;
				var shippingDiscountTotal = 0;
				var orderDiscountTotal = 0;
				
				if (response.data.ShoppingBag.ShippingDiscounts) {
					shippingDiscountTotal = response.data.ShoppingBag.ShippingDiscounts.reduce(function (sum, elem) {
						return sum + elem.DiscountTotal;
					}, 0);
				}
				
				if (response.data.ShoppingBag.OrderDiscounts) {
					orderDiscountTotal = response.data.ShoppingBag.OrderDiscounts.reduce(function (sum, elem) {
						return sum + elem.DiscountTotal;
					}, 0);
				}
				
				$scope.data.ShippingDiscountTotal = shippingDiscountTotal;
				$scope.data.OrderDiscountTotal = orderDiscountTotal;
				
			}, function errorCallback(response) {
				console.error(response);
			});
		}
		
		function scrollToActive() {
			$location.hash('activeStep');
			$anchorScroll();
		}
		
		// same tab
		function initCitizenPayFlowSameTab(initialFlowUrl) {
			$scope.busy = true;
			$http.get(initialFlowUrl)
				.then(function (response) {
					if (response.data.success) {
						$window.location.href = response.data.value.redirectURL;
					} else {
						showCitizenPayError();
						$scope.busy = false;
					}
					
				}, function (error) {
					showCitizenPayError();
					$scope.busy = false;
				});
		}
		
		// iFrame in popup
		function initCitizenPayFlowPopup(initialFlowUrl) {
			$scope.busy = true;
			$http.get(initialFlowUrl)
				.then(function (response) {
					if (response.data.success) {
						var template = '<iframe id="citizenPayInitialFlowFrame" style="border: 0;" width="100%" height="100%" src="' + response.data.value.redirectURL + '"></iframe>';
						ngDialog.open({
							template: template,
							plain: true,
							className: 'ngdialog-theme-plain ngdialog-citizenpay-initialflow',
							showClose: true,
							closeByEscape: false,
							preCloseCallback: function () {
								$scope.busy = false;
								$window.location.href = appSettings.getUrl('citizenpay/completeflow/', true);
								return true;
							}
						});
					} else {
						showCitizenPayError();
						$scope.busy = false;
					}
					
				}, function (error) {
					showCitizenPayError();
					$scope.busy = false;
				});
		}
		
		// iFrame sdk
		function initCitizenPayFlowSdk(data) {
			$scope.busy = true;
			
			var url = appSettings.getUrl('citizenpay/GetInitialFlowData/', true);
			
			$http.get(url)
				.then(function (response) {
					// CitizenPay Sdk requires PascalCase
					if (response.data.Success) {
						var initiateFlowRequestData = response.data.Value;
						
						// for testing: these credentials support sdk
						// initiateFlowRequestData.Token = 'a0ea6a6f11b54e40bca008e2fdf89198';
						// initiateFlowRequestData.MerchantId = '1dc3c3b169c348e6a66f251e552a00f0';
						
						var initiateFlowRequest = {
							"MerchantId": initiateFlowRequestData.MerchantId,
							"Customer": {
								"FirstName": initiateFlowRequestData.Customer.FirstName,
								"LastName": initiateFlowRequestData.Customer.LastName,
								"Email": initiateFlowRequestData.Customer.Email,
								"MobilePhoneNumber": initiateFlowRequestData.Customer.MobilePhoneNumber
							},
							"BillingAddress": {
								"AddressLine1": initiateFlowRequestData.BillingAddress.AddressLine1,
								"AddressLine2": initiateFlowRequestData.BillingAddress.AddressLine2,
								"City": initiateFlowRequestData.BillingAddress.City,
								"State": initiateFlowRequestData.BillingAddress.State,
								"PostalCode": initiateFlowRequestData.BillingAddress.PostalCode
							},
							"RequestedAmount": initiateFlowRequestData.RequestedAmount,
							"SourcePageType": initiateFlowRequestData.SourcePageType,
							"CompletionMethod": initiateFlowRequestData.CompletionMethod,
							"CallbackURL": initiateFlowRequestData.CallbackUrl,
							"WindowBehavior": initiateFlowRequestData.WindowBehavior
						}
						
						console.log(initiateFlowRequest);
						
						var client = Sdk.init(initiateFlowRequestData.Token);
						if (!client) {
							showCitizenPayError();
							$scope.busy = false;
							return;
						}
						
						client.initiateFlow(initiateFlowRequest)
							.then(function (response) {
									console.log("Citizen Pay initialization - success");
									$scope.busy = false;
								},
								function (error) {
									console.error("Citizen Pay initialization - failure");
									showCitizenPayError();
									$scope.busy = false;
								});
					} else {
						showCitizenPayError();
						$scope.busy = false;
					}
					
				}, function (error) {
					showCitizenPayError();
					$scope.busy = false;
				});
		}
		
		function showCitizenPayError() {
			ngDialog.open({
				template: '<div><h4>Warning</h4></div><div class="ngdialog-message"> \
						  <p class="message">An error occurred, please try again or try an alternate form of payment.</p></div>',
				className: 'ngdialog-theme-plain warningMessage',
				plain: 'true'
			});
		}
		
		refreshCheckoutItems();
		
		scrollToActive();
		
		$scope.$on('checkout.busy', () => $timeout(() => $scope.$apply(() => $scope.busy = true)));
		$scope.$on('checkout.ready', () => $timeout(() => $scope.$apply(() => $scope.busy = false)));
		
		if($injector.has('paymentProvider')) {
			let paymentType = $injector.get('paymentProvider');
			$scope.model.paymentType = paymentType;
		}
	}
	
	angular
		.module('app')
		.controller('CheckoutCtrl', ['$scope', '$injector', '$element', '$timeout', '$http', '$location', '$window', '$anchorScroll', 'ngDialog', 'spinner', 'appSettings', 'shoppingBagId', 'uiGmapGoogleMapApi', CheckoutCtrl]);
	
})();
;
(function () {
	'use strict';
	
	window.bdApp.directive('paypalCheckout', ($paypalAddress, $paypalAction) => ({
		scope: false,
		link(scope, elem) {
			const paypalOverlay = angular.element('<div class="paypal-overlay"></div>');
			
			const createOrder = (data, actions) => {
				scope.$emit('checkout.busy');
				scope.$broadcast('checkout.busy');
				
				const model = scope.data.model;
				
				const shippingPref = $paypalAddress ? "SET_PROVIDED_ADDRESS" : "NO_SHIPPING";
				
				const address = $paypalAddress ? {
					"admin_area_2": $paypalAddress.City,
					"postal_code": $paypalAddress.PostalCode,
					"country_code": $paypalAddress.CountryCode,
					"address_line_1": $paypalAddress.AddressLine1,
				} : {};
				
				const items = model.ShoppingBag.Items.map(item => ({
					"quantity": 1,
					"name": item.Sku.ProductCode,
					"description": item.Sku.ProductName,
					"unit_amount": {
						"currency_code": "USD",
						"value": item.TotalAmount,
					},
				}));
				
				return actions.order.create({
					"purchase_units": [
						{
							"description": "Tile & Stone",
							"amount": {
								"value": model.AmountDue,
								"currency_code": "USD",
								"breakdown": {
									"item_total": {
										"currency_code": "USD",
										"value": model.ShoppingBag.SubTotal
									},
									"shipping": {
										"currency_code": "USD",
										"value": model.ShoppingBag.ShippingAmount
									},
									"tax_total": {
										"currency_code": "USD",
										"value": model.TaxAmount
									},
									"handling": {
										"currency_code": "USD",
										"value": model.MiscChargesAmount
									},
								}
							},
							"items": items,
							"shipping": {address},
						}
					],
					"application_context": {
						"brand_name": "Bedrosians",
						"shipping_preference": shippingPref,
					}
				});
			};
			
			const onApprove = (data, actions) => {
				actions.order.authorize().then(function (authorization) {
					scope.$emit('checkout.busy');
					scope.$broadcast('checkout.busy');
					let success = authorization.status === "COMPLETED";
					let authorizationID = authorization.purchase_units[0].payments.authorizations[0].id;
					window.location = `${$paypalAction}?success=${success}&orderId=${data.orderID}&authorizationId=${authorizationID}`;
				});
			};
			
			const onCancel = () => {
				scope.$emit('checkout.ready');
				scope.$broadcast('checkout.ready');
			};
			
			const onInit = (data, actions) => {
				actions.disable();
				scope.$watch('data.model.ShoppingBag', (value) => {
					if (!value) {
						actions.disable();
						elem.append(paypalOverlay);
					} else {
						actions.enable();
						paypalOverlay.remove();
					}
				});
			}
			
			const onError = (error) => {
				scope.$emit('checkout.ready');
				scope.$broadcast('checkout.ready');
				alert("An error occurred, please try again or try an alternate form of payment.")
			};
			
			const node = elem.get(0);
			
			const style = {
				color: "black",
				borderRadius: 12,
				label: "checkout",
			};
			
			elem.append(paypalOverlay);
			
			paypal.Buttons({
				style,
				onInit,
				onError,
				onCancel,
				onApprove,
				createOrder,
			}).render(node);
		}
	}))
})();
(function () {
	'use strict';
	window.bdApp.controller("RegistrationController", ($scope, $timeout) => {
		$scope.account = {
			Email: null,
			Password: null,
			ConfirmPassword: null,
		};
		$scope.form = {
			recaptchaToken: null,
			submit(event) {
				event.preventDefault();

				if ($scope.registrationForm.$invalid) return;

				if (!grecaptcha) return;

				grecaptcha.ready(() => {
					return grecaptcha.execute($scope.form.recaptchaToken, {action: "QuickRegister"})
						.then((token) => {
							$timeout(() => {
								$scope.$apply(() => {
									$scope.form.recaptchaToken = token;
									$timeout(() => event.target.submit());
								});
							})
						});
				});
			},
		};
	});
})()
;
(function () {
	'use strict';

	angular.module('app')
		.controller('branchLocatorController', [
			'$scope', '$rootScope', '$window', '$http', 'spinner', '$geolocation', 'appSettings', '$cookies', 'branchLocatorService', 'ngDialog',
			function ($scope, $rootScope, $window, $http, spinner, $geolocation, appSettings, $cookies, branchLocatorService, ngDialog) {

				$scope.init = function (state, city, code, shippingState, shippingCountry) {
					$scope.branchState = state;
					$scope.branchCity = city;
					$scope.branchCode = code;

					branchLocatorService.SetShippingStateName(shippingState);
					branchLocatorService.SetShippingCountryName(shippingCountry);

					var wasGeoLocated = branchLocatorService.GetlocationWasGeoLocated();

					if (!wasGeoLocated) {
						var geoUrl = appSettings.getUrl("shipping/ChangeLocationToClosest/", true);
						$geolocation.getCurrentPosition({
							timeout: 60000
						}).then(function (position) {
							$http({
								method: 'POST',
								url: geoUrl,
								data: {
									lat: position.coords.latitude,
									lon: position.coords.longitude
								}
							}).then(function (response) {
								$scope.setBranch(response.data.context);
								branchLocatorService.SetLocationWasGeoLocated();
								if (response.data.context.StateCode !== shippingState) {
									window.location.reload();
								}
							});
						});
					}
				};

				$scope.$on('branchChanged', function (event, branch) {
					branchLocatorService.SetStateNameLocated(branch.branchState);
					$scope.branchState = branch.branchState;
					$scope.branchCity = branch.branchCity;
					$scope.branchCode = branch.branchCode;
				});

				$scope.selectIt = function () {
					$scope.data = {
						busy: true,
						ourLocationsUrl: appSettings.getUrl("our-locations/", true)
					};

					$scope.selectLocationDialog = ngDialog.open({
						template: appSettings.getUrl("scripts/app/common/directives/selectLocation.dialog.html"),
						className: '',
						showClose: false,
						scope: $scope,
						controller: [
							'$scope', '$http', function ($scope, $http) {
								$http.get(appSettings.getUrl('our-locations/', true))
									.then(function (response) {
										$scope.data.locations = response.data;
										$scope.data.busy = false;
									});
							}
						]
					});
				};

				$scope.chooseIt = function (locationCode) {
					branchLocatorService.ChooseBranchByCode(locationCode, function (response) {
						$scope.selectLocationDialog.close(true);
						$scope.setBranch(response.data.context);
					});
				};

				$scope.setBranch = function (context) {
					var branch = {
						branchState: context.BranchState,
						branchCity: context.BranchCity,
						branchCode: context.BranchCode
					};

					$rootScope.$broadcast('branchChanged', branch);
				};

				$scope.selectState = function () {

					$scope.data = {
						states: [],
						busy: false,
						ourStatesUrl: appSettings.getUrl("home/GetAllStates/", true)
					};

					$scope.selectStateDialog = ngDialog.open({
						template: appSettings.getUrl("scripts/app/common/directives/selectState.dialog.html"),
						className: '',
						showClose: false,
						scope: $scope,
						controller: [
							'$scope', '$http', function ($scope, $http) {

								$scope.data.busy = true;

								$http.get(appSettings.getUrl('home/GetAllStates', true))
									.then(function (response) {
										$scope.data.states = response.data.states;
										$scope.data.busy = false;
									}, function (response) {
										$scope.data.busy = false;
									});
							}
						]
					});
				};

				$scope.chooseState = function (stateAbbreviation) {
					if ($scope.busy) return;

					$scope.selectStateDialog.close(true);

					$scope.busy = true;

					spinner.startLoad();

					branchLocatorService.ChooseStateByAbbreviation(stateAbbreviation)
						.then(function (response) {
							window.location.reload();
						});
				};

			}
		]);
}());
;
(function () {
	'use strict';

	window.bdApp.controller('MenuCtrl', ['$scope', '$window', '$http', 'appSettings', '$injector', function ($scope, $window, $http, appSettings, $injector) {
		$http.get(appSettings.getUrl('home/GetAllStates', true)).then((res) => $scope.locations = res.data.states);

		$scope.locationsUrl = $injector.has('locations-url') ? $injector.get('locations-url') : null;

		$scope.accountMenu = $injector.has('account-menu') ? $injector.get('account-menu') : [];

		const menu = $injector.has('main-menu') ? $injector.get('main-menu') : [];

		const configMenuItem = (item, parent) => {
			item.hasChild = item.children.length > 0;
			item.isParent = !parent || item.children.length > 0;
			item.isClearance = item.title.toLowerCase() === 'clearance';
			item.isShopThisLook = item.title.toLowerCase() === 'shop this look';
			item.isInspiration = item.title.toLowerCase() === 'inspiration' || (parent && parent.isInspiration) || false;
			return item;
		}

		const configImages = (item, parent) => {
			if (item.isShopThisLook || item.isInspiration) {
				let itemTitle = item.title.toLowerCase().replace(/[\W_]+/g, '_');
				let parentTitle = parent.title.toLowerCase().replace(/[\W_]+/g, '_');
				item.image = `https://res.cloudinary.com/bedrosians/image/upload/f_auto,c_fill,w_400,h_250/v1/assets/content/menu/${parentTitle}-${itemTitle}`;
			}
			return item;
		}

		const configMenu = (item, parent) => {
			item = configMenuItem(item, parent);
			if (parent) item = configImages(item, parent);
			if (item.hasChild) item.children = item.children.map(i => configMenu(i, item));
			return item;
		}

		$scope.menu = menu.map(i => configMenu(i));

		$scope.initShoppingBag = function () {
			$http({
				method: 'GET',
				url: appSettings.getUrl('home/AccountInformation', true)
			}).then(function (response) {
				$scope.showShoppingBagItemIcon = response.data.itemsCount > 0;
				$scope.itemsCount = response.data.itemsCount;
			});
		};

		$scope.$on('shoppingBagItemsChanged', function (event, itemCount) {
			$scope.showShoppingBagItemIcon = itemCount > 0;
			$scope.itemsCount = itemCount;
			});
	}]);
}());
;
(function () {
	'use strict';

	window.bdApp.run(['$serviceInjector',
		(injector) => injector.inject({
			'$settings': 'appSettings',
		})
	])

	window.bdApp.controller('SearchController', [
		'$q',
		'$http',
		'$scope',
		(
			$q,
			$http,
			$scope,
		) => {
			$scope.getSuggestionsUrl = (item, facet) => {
				const queryObject = {
					[facet]: item.category,
					criteria: item.searchString,
				};
				const filteredQueryObject = _.reduce(queryObject, (result, value, key) => {
					if (value) result[key] = value;
					return result;
				}, {});
				const query = new URLSearchParams(filteredQueryObject).toString();
				return $scope.$root.$settings.getUrl(`product/list/?${query}`, true);
			}

			$scope.getProductUlr = (item) => {
				const query = new URLSearchParams({
					itemNo: item.ProductCode
				}).toString();
				return $scope.$root.$settings.getUrl(`product/detail/${item.UrlFriendlyStyleName}/?${query}`, true);
			}

			$scope.$watch('model.query', (newValue, oldValue) => {
				if (!newValue || newValue === oldValue) return;
				const query = newValue;
				const headers = {'X-Requested-With': 'XMLHttpRequest'};
				$scope.pageResultsUrl = $scope.$root.$settings.getUrl('search/content/?q=' + query, true);
				$scope.suggestionResultsUrl = $scope.$root.$settings.getUrl('search/querysuggestions/?input=' + query, true);
				$scope.productResultsUrl = $scope.$root.$settings.getUrl('product/list/?criteria=' + query + '&storeNavInfo=false', true);
				Promise.all([
					$http({url: $scope.pageResultsUrl, headers: headers}),
					$http({url: $scope.productResultsUrl, headers: headers}),
					$http({url: $scope.suggestionResultsUrl, headers: headers}),
				]).then(([pages, products, suggestions]) => {
					$scope.$apply(() => {
						$scope.data.pages = pages.data;
						$scope.data.products = products.data;
						$scope.data.suggestions = suggestions.data;
					})
				}).catch(e => console.error(e))
			});
		}])
})()
;
(function withAngular(angular) {
	'use strict';

	var directiveName = 'socialshare'
	  , socialshareProviderNames = ['facebook', 'twitter', 'linkedin', 'google+', 'pinterest', 'tumblr', 'reddit', 'stumbleupon', 'buffer', 'digg', 'delicious', 'vk', 'pocket', 'wordpress', 'flipboard', 'xing', 'hackernews', 'evernote']
	  , socialshareConfigurationProvider = /*@ngInject*/ function socialshareConfigurationProvider() {

	  	var socialshareConfigurationDefault = [{
	  		'provider': 'facebook',
	  		'conf': {
	  			'url': '',
	  			'text': '',
	  			'media': '',
	  			'type': '',
	  			'via': '',
	  			'to': '',
	  			'from': '',
	  			'ref': '',
	  			'display': '',
	  			'source': '',
	  			'caption': '',
	  			'redirectUri': '',
	  			'trigger': 'click',
	  			'popupHeight': 300,
	  			'popupWidth': 400
	  		}
	  	},
		  {
		  	'provider': 'twitter',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'via': '',
		  		'hashtags': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'linkedin',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'description': '',
		  		'source': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'reddit',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'subreddit': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'vk',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'digg',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'delicious',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'stumbleupon',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'pinterest',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'google+',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'tumblr',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'buffer',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'via': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'pocket',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'flipboard',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'hackernews',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'wordpress',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'xing',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'media': '',
		  		'follow': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  },
		  {
		  	'provider': 'evernote',
		  	'conf': {
		  		'url': '',
		  		'text': '',
		  		'trigger': 'click',
		  		'popupHeight': 300,
		  		'popupWidth': 400
		  	}
		  }];

	  	return {
	  		'configure': function configure(configuration) {

	  			var configIndex = 0
				  , configurationKeys
				  , configurationIndex
				  , aConfigurationKey
				  , configElement
				  , internIndex = 0
				//this is necessary becuase provider run before any service
				//so i have to take the log from another injector
				, $log = angular.injector(['ng']).get('$log');

	  			if (configuration && configuration.length > 0) {
	  				for (; configIndex < configuration.length; configIndex += 1) {
	  					if (configuration[configIndex].provider && socialshareProviderNames.indexOf(configuration[configIndex].provider) > -1) {

	  						for (; internIndex < socialshareConfigurationDefault.length; internIndex += 1) {
	  							configElement = socialshareConfigurationDefault[internIndex];

	  							if (configElement &&
								  configElement.provider &&
								  configuration[configIndex].provider === configElement.provider) {

	  								configurationKeys = Object.keys(configElement.conf);
	  								configurationIndex = 0;

	  								for (; configurationIndex < configurationKeys.length; configurationIndex += 1) {

	  									aConfigurationKey = configurationKeys[configurationIndex];
	  									if (aConfigurationKey && configuration[configIndex].conf[aConfigurationKey]) {

	  										configElement.conf[aConfigurationKey] = configuration[configIndex].conf[aConfigurationKey];
	  									}
	  								}
	  							}
	  						}
	  					} else {
	  						$log.warn('Invalid provider at element ' + configIndex + ' with name:' + configuration[configIndex].provider);
	  					}
	  				}
	  			}
	  		}
		  , '$get': /*@ngInject*/ function instantiateProvider() {

		  	return socialshareConfigurationDefault;
		  }
	  	};
	  }
	  , socialshareDirective = /*@ngInject*/["$window", "$location", "socialshareConf", "$log", function socialshareDirective($window, $location, socialshareConf, $log) {

	  	var linkingFunction = function linkingFunction($scope, element, attrs) {

	  		// observe the values in each of the properties so that if they're updated elsewhere,
	  		// they are updated in this directive.
	  		var configurationElement
			, index = 0
			, onEventTriggered = function onEventTriggered() {
				/*eslint-disable no-use-before-define*/
				switch (attrs.socialshareProvider) {
					case 'facebook': {

						facebookShare($window, $location, attrs);
						break;
					}
					case 'google+': {

						googlePlusShare($window, $location, attrs);
						break;
					}
					case 'twitter': {

						twitterShare($window, $location, attrs);
						break;
					}
					case 'stumbleupon': {

						stumbleuponShare($window, $location, attrs);
						break;
					}
					case 'reddit': {

						redditShare($window, $location, attrs);
						break;
					}
					case 'pinterest': {

						pinterestShare($window, $location, attrs);
						break;
					}
					case 'linkedin': {

						linkedinShare($window, $location, attrs);
						break;
					}
					case 'digg': {

						diggShare($window, $location, attrs);
						break;
					}
					case 'tumblr': {

						tumblrShare($window, $location, attrs);
						break;
					}
					case 'delicious': {

						deliciousShare($window, $location, attrs);
						break;
					}
					case 'vk': {

						vkShare($window, $location, attrs);
						break;
					}
					case 'buffer': {

						bufferShare($window, $location, attrs);
						break;
					}
					case 'pocket': {

						pocketShare($window, $location, attrs);
						break;
					}
					case 'wordpress': {

						wordpressShare($window, $location, attrs);
						break;
					}
					case 'flipboard': {

						flipboardShare($window, $location, attrs);
						break;
					}
					case 'hackernews': {

						hackernewsShare($window, $location, attrs);
						break;
					}
					case 'xing': {

						xingShare($window, $location, attrs);
						break;
					}
					case 'evernote': {

						evernoteShare($window, $location, attrs);
						break;
					}
					default: {
						return true;
					}
				}
			};
	  		/*eslint-enable no-use-before-define*/
	  		//looking into configuration if there is a config for the current provider
	  		for (; index < socialshareConf.length; index += 1) {
	  			if (socialshareConf[index].provider === attrs.socialshareProvider) {
	  				configurationElement = socialshareConf[index];
	  				break;
	  			}
	  		}

	  		if (socialshareProviderNames.indexOf(configurationElement.provider) === -1) {
	  			$log.warn('Invalid Provider Name : ' + attrs.socialshareProvider);
	  		}

	  		//if some attribute is not define provide a default one
	  		attrs.socialshareUrl = attrs.socialshareUrl || configurationElement.conf.url;
	  		attrs.socialshareText = attrs.socialshareText || configurationElement.conf.text;
	  		attrs.socialshareMedia = attrs.socialshareMedia || configurationElement.conf.media;
	  		attrs.socialshareType = attrs.socialshareType || configurationElement.conf.type;
	  		attrs.socialshareVia = attrs.socialshareVia || configurationElement.conf.via;
	  		attrs.socialshareTo = attrs.socialshareTo || configurationElement.conf.to;
	  		attrs.socialshareFrom = attrs.socialshareFrom || configurationElement.conf.from;
	  		attrs.socialshareRef = attrs.socialshareRef || configurationElement.conf.ref;
	  		attrs.socialshareDislay = attrs.socialshareDislay || configurationElement.conf.display;
	  		attrs.socialshareSource = attrs.socialshareSource || configurationElement.conf.source;
	  		attrs.socialshareCaption = attrs.socialshareCaption || configurationElement.conf.caption;
	  		attrs.socialshareRedirectUri = attrs.socialshareRedirectUri || configurationElement.conf.redirectUri;
	  		attrs.socialshareTrigger = attrs.socialshareTrigger || configurationElement.conf.trigger;
	  		attrs.socialsharePopupHeight = attrs.socialsharePopupHeight || configurationElement.conf.popupHeight;
	  		attrs.socialsharePopupWidth = attrs.socialsharePopupWidth || configurationElement.conf.popupWidth;
	  		attrs.socialshareSubreddit = attrs.socialshareSubreddit || configurationElement.conf.subreddit;
	  		attrs.socialshareDescription = attrs.socialshareDescription || configurationElement.conf.description;
	  		attrs.socialshareFollow = attrs.socialshareFollow || configurationElement.conf.follow;
	  		attrs.socialshareHashtags = attrs.socialshareHashtags || configurationElement.conf.hashtags;

	  		element.bind(attrs.socialshareTrigger, onEventTriggered);
	  	};

	  	return {
	  		'restrict': 'A',
	  		'link': linkingFunction
	  	};
	  }]
	  , manageFacebookShare = function manageFacebookShare($window, $location, attrs) {
	  	if (attrs.socialshareType && attrs.socialshareType === 'feed') {
	  		// if user specifies that they want to use the Facebook feed dialog (https://developers.facebook.com/docs/sharing/reference/feed-dialog/v2.4)
	  		var urlString = 'https://www.facebook.com/dialog/feed?display=popup';

	  		if (attrs.socialshareVia) {
	  			urlString += '&app_id=' + encodeURIComponent(attrs.socialshareVia);
	  		}

	  		if (attrs.socialshareRedirectUri) {
	  			urlString += '&redirect_uri=' + encodeURIComponent(attrs.socialshareRedirectUri);
	  		}
	  		if (attrs.socialshareUrl) {
	  			urlString += '&link=' + encodeURIComponent(attrs.socialshareUrl);
	  		}

	  		if (attrs.socialshareTo) {
	  			urlString += '&to=' + encodeURIComponent(attrs.socialshareTo);
	  		}

	  		if (attrs.socialshareDisplay) {
	  			urlString += '&display=' + encodeURIComponent(attrs.socialshareDisplay);
	  		}

	  		if (attrs.socialshareRef) {
	  			urlString += '&ref=' + encodeURIComponent(attrs.socialshareRef);
	  		}

	  		if (attrs.socialshareFrom) {
	  			urlString += '&from=' + encodeURIComponent(attrs.socialshareFrom);
	  		}

	  		if (attrs.socialshareDescription) {
	  			urlString += '&description=' + encodeURIComponent(attrs.socialshareDescription);
	  		}

	  		if (attrs.socialshareText) {
	  			urlString += '&name=' + encodeURIComponent(attrs.socialshareText);
	  		}

	  		if (attrs.socialshareCaption) {
	  			urlString += '&caption=' + encodeURIComponent(attrs.socialshareCaption);
	  		}

	  		if (attrs.socialshareMedia) {
	  			urlString += '&picture=' + encodeURIComponent(attrs.socialshareMedia);
	  		}

	  		if (attrs.socialshareSource) {
	  			urlString += '&source=' + encodeURIComponent(attrs.socialshareSource);
	  		}

	  		$window.open(
			  urlString,
			  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
			  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);

	  	} else {
	  		//otherwise default to using sharer.php
	  		$window.open(
			  'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl())
			  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
			  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  	}
	  }
	  , manageTwitterShare = function manageTwitterShare($window, $location, attrs) {
	  	var urlString = 'https://www.twitter.com/intent/tweet?';

	  	if (attrs.socialshareText) {
	  		urlString += 'text=' + encodeURIComponent(attrs.socialshareText);
	  	}

	  	if (attrs.socialshareVia) {
	  		urlString += '&via=' + encodeURIComponent(attrs.socialshareVia);
	  	}

	  	if (attrs.socialshareHashtags) {
	  		urlString += '&hashtags=' + encodeURIComponent(attrs.socialshareHashtags);
	  	}

	  	//default to the current page if a URL isn't specified
	  	urlString += '&url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageGooglePlusShare = function manageGooglePlusShare($window, $location, attrs) {

	  	$window.open(
		  'https://plus.google.com/share?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl())
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageRedditShare = function manageRedditShare($window, $location, attrs) {
	  	var urlString = 'https://www.reddit.com/';

	  	if (attrs.socialshareSubreddit) {
	  		urlString += 'r/' + attrs.socialshareSubreddit + '/submit?url=';
	  	} else {
	  		urlString += 'submit?url=';
	  	}
	  	/*-
		* Reddit isn't responsive and at default width for our popups (500 x 500), everything is messed up.
		* So, overriding the width if it is less than 900 (played around to settle on this) and height if
		* it is less than 650px.
		*/
	  	if (attrs.socialsharePopupWidth < 900) {
	  		attrs.socialsharePopupWidth = 900;
	  	}

	  	if (attrs.socialsharePopupHeight < 650) {
	  		attrs.socialsharePopupHeight = 650;
	  	}

	  	$window.open(
		  urlString + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + '&title=' + encodeURIComponent(attrs.socialshareText)
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageStumbleuponShare = function manageStumbleuponShare($window, $location, attrs) {

	  	$window.open(
		  'https://www.stumbleupon.com/submit?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + '&title=' + encodeURIComponent(attrs.socialshareText)
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageLinkedinShare = function manageLinkedinShare($window, $location, attrs) {
	  	/*
		* Refer: https://developer.linkedin.com/docs/share-on-linkedin
		* Tab: Customized URL
		*/
	  	var urlString = 'https://www.linkedin.com/shareArticle?mini=true';

	  	urlString += '&url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	if (attrs.socialshareText) {
	  		urlString += '&title=' + encodeURIComponent(attrs.socialshareText);
	  	}

	  	if (attrs.socialshareDescription) {
	  		urlString += '&summary=' + encodeURIComponent(attrs.socialshareDescription);
	  	}

	  	if (attrs.socialshareSource) {
	  		urlString += '&source=' + encodeURIComponent(attrs.socialshareSource);
	  	}

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , managePinterestShare = function managePinterestShare($window, $location, attrs) {

	  	$window.open(
		  'https://www.pinterest.com/pin/create/button/?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + '&media=' + encodeURIComponent(attrs.socialshareMedia) + '&description=' + encodeURIComponent(attrs.socialshareText)
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageDiggShare = function manageDiggShare($window, $location, attrs) {

	  	$window.open(
		  'https://www.digg.com/submit?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + '&title=' + encodeURIComponent(attrs.socialshareText)
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageTumblrShare = function manageTumblrShare($window, $location, attrs) {

	  	if (attrs.socialshareMedia) {
	  		var urlString = 'https://www.tumblr.com/share/photo?source=' + encodeURIComponent(attrs.socialshareMedia);

	  		if (attrs.socialshareText) {
	  			urlString += '&caption=' + encodeURIComponent(attrs.socialshareText);
	  		}

	  		$window.open(
			  urlString,
			  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
			  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  	} else {

	  		$window.open(
			  'https://www.tumblr.com/share/link?url=' + encodeURIComponent(attrs.socialshareUrl) + '&description=' + encodeURIComponent(attrs.socialshareText)
			  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
			  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  	}
	  }
	  , manageVkShare = function manageVkShare($window, $location, attrs) {

	  	$window.open(
		  'https://www.vk.com/share.php?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl())
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageDeliciousShare = function manageDeliciousShare($window, $location, attrs) {

	  	$window.open(
		  'https://www.delicious.com/save?v=5&noui&jump=close&url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + '&title=' + encodeURIComponent(attrs.socialshareText)
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageBufferShare = function manageBufferShare($window, $location, attrs) {
	  	var urlString = 'https://bufferapp.com/add?';

	  	if (attrs.socialshareText) {
	  		urlString += 'text=' + encodeURIComponent(attrs.socialshareText);
	  	}

	  	if (attrs.socialshareVia) {
	  		urlString += '&via=' + encodeURIComponent(attrs.socialshareVia);
	  	}

	  	//default to the current page if a URL isn't specified
	  	urlString += '&url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageHackernewsShare = function manageHackernewsShare($window, $location, attrs) {
	  	var urlString = 'https://news.ycombinator.com/submitlink?';

	  	if (attrs.socialshareText) {
	  		urlString += 't=' + encodeURIComponent(attrs.socialshareText) + '&';
	  	}
	  	//default to the current page if a URL isn't specified
	  	urlString += 'u=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		 urlString,
		 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		+ ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageFlipboardShare = function manageFlipboardShare($window, $location, attrs) {
	  	var urlString = 'https://share.flipboard.com/bookmarklet/popout?v=2&';

	  	if (attrs.socialshareText) {
	  		urlString += 'title=' + encodeURIComponent(attrs.socialshareText) + '&';
	  	}

	  	//default to the current page if a URL isn't specified
	  	urlString += 'url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , managePocketShare = function managePocketShare($window, $location, attrs) {
	  	var urlString = 'https://getpocket.com/save?';

	  	if (attrs.socialshareText) {
	  		urlString += 'text=' + encodeURIComponent(attrs.socialshareText) + '&';
	  	}

	  	//default to the current page if a URL isn't specified
	  	urlString += 'url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageWordpressShare = function manageWordpressShare($window, $location, attrs) {
	  	var urlString = 'http://wordpress.com/press-this.php?';

	  	if (attrs.socialshareText) {
	  		urlString += 't=' + encodeURIComponent(attrs.socialshareText) + '&';
	  	}
	  	if (attrs.socialshareMedia) {
	  		urlString += 'i=' + encodeURIComponent(attrs.socialshareMedia) + '&';
	  	}

	  	//default to the current page if a URL isn't specified
	  	urlString += 'u=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	$window.open(
		  urlString,
		  'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageXingShare = function manageXingShare($window, $location, attrs) {
	  	var followUrl = '';

	  	if (attrs.socialshareFollow) {
	  		followUrl = '&follow_url=' + encodeURIComponent(attrs.socialshareFollow);
	  	}
	  	$window.open(
		  'https://www.xing.com/spi/shares/new?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl()) + followUrl
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , manageEvernoteShare = function manageEvernoteShare($window, $location, attrs) {

	  	var urlString = 'http://www.evernote.com/clip.action?url=' + encodeURIComponent(attrs.socialshareUrl || $location.absUrl());

	  	if (attrs.socialshareText) {
	  		urlString += '&title=' + encodeURIComponent(attrs.socialshareText);
	  	}

	  	$window.open(
		  urlString
		  , 'sharer', 'toolbar=0,status=0,width=' + attrs.socialsharePopupWidth + ',height=' + attrs.socialsharePopupHeight
		  + ',top=' + ($window.innerHeight - attrs.socialsharePopupHeight) / 2 + ',left=' + ($window.innerWidth - attrs.socialsharePopupWidth) / 2);
	  }
	  , facebookShare = manageFacebookShare
	  , twitterShare = manageTwitterShare
	  , googlePlusShare = manageGooglePlusShare
	  , redditShare = manageRedditShare
	  , stumbleuponShare = manageStumbleuponShare
	  , linkedinShare = manageLinkedinShare
	  , pinterestShare = managePinterestShare
	  , diggShare = manageDiggShare
	  , tumblrShare = manageTumblrShare
	  , vkShare = manageVkShare
	  , deliciousShare = manageDeliciousShare
	  , bufferShare = manageBufferShare
	  , hackernewsShare = manageHackernewsShare
	  , flipboardShare = manageFlipboardShare
	  , pocketShare = managePocketShare
	  , wordpressShare = manageWordpressShare
	  , xingShare = manageXingShare
	  , evernoteShare = manageEvernoteShare;


	angular.module('720kb.socialshare', [])
	.provider(directiveName + 'Conf', socialshareConfigurationProvider)
	.directive(directiveName, socialshareDirective);
}(angular));;
angular
    .module('app')
    .directive('bdplAccordion', ['$document', function ($document) {
        return {
            link: function (scope, element, attr) {
                $document.ready(() => {
                    function Accordion(domNode) {
                        this.domNode = domNode;
                    }

                    Accordion.prototype.init = function () {
                        this.triggers = Array
                            .from(this.domNode.querySelectorAll('[bdpl-accordion-tigger]'))
                            .map((el) => {
                                const trigger = new AccordionTrigger(el, this);
                                trigger.init();
                                return trigger;
                            });

                        this.accordionLength = this.triggers.length;
                    }

                    Accordion.prototype.setFocusToPrevItem = function (currentItem) {
                        const currentIndex = this.triggers.indexOf(currentItem);
                        if (currentIndex === 0) {
                            this.triggers[this.accordionLength - 1].domNode.focus();
                        } else {
                            this.triggers[currentIndex - 1].domNode.focus();
                        }
                    }

                    Accordion.prototype.setFocusToNextItem = function (currentItem) {
                        const currentIndex = this.triggers.indexOf(currentItem);
                        if (currentIndex === this.accordionLength - 1) {
                            this.triggers[0].domNode.focus();
                        } else {
                            this.triggers[currentIndex + 1].domNode.focus();
                        }
                    }

                    function AccordionTrigger(domNode, controller) {
                        this.controller = controller;
                        this.domNode = domNode;
                        this.panel = document.getElementById(this.domNode.getAttribute('aria-controls'));
                    }

                    AccordionTrigger.prototype.init = function () {
                        this.domNode.addEventListener('click', this.handleClick.bind(this));
                        this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
                        this.domNode.setAttribute('aria-expanded', false);

                        this.panel.setAttribute('role', 'region');
                        this.panel.setAttribute('aria-labelledby', this.domNode.getAttribute('id'));
                        this.panel.hidden = true;
                    }

                    AccordionTrigger.prototype.open = function () {
                        this.domNode.setAttribute('aria-expanded', true);
                        this.panel.hidden = false;
                    }

                    AccordionTrigger.prototype.close = function () {
                        this.domNode.setAttribute('aria-expanded', false);
                        this.panel.hidden = true;
                    }

                    AccordionTrigger.prototype.handleClick = function () {
                        const isExpanded = Boolean(this.domNode.getAttribute('aria-expanded') === 'true');

                        if (isExpanded) {
                            this.domNode.setAttribute('aria-expanded', false);
                            this.panel.hidden = true;
                        } else {
                            this.controller.triggers.map((trigger) => {
                                if (trigger.domNode === this.domNode) {
                                    trigger.open()
                                } else {
                                    trigger.close()
                                }
                            });
                        }
                    }

                    AccordionTrigger.prototype.handleKeydown = function (event) {
                        var flag = false;
                        switch (event.code) {
                            case 'Space':
                                this.handleClick();
                                flag = true;
                                break;
                            case 'ArrowUp':
                                this.controller.setFocusToPrevItem(this);
                                flag = true;
                                break;
                            case 'ArrowDown':
                                this.controller.setFocusToNextItem(this);
                                flag = true;
                                break;
                            case 'Home':
                                this.controller.triggers[0].domNode.focus();
                                flag = true;
                                break;
                            case 'End':
                                this.controller.triggers[this.controller.triggers.length - 1].domNode.focus();
                                flag = true;
                                break;
                            default:
                                break;
                        }

                        if (flag) {
                            event.preventDefault();
                            event.stopPropagation();
                        }
                    }

                    const accordion = new Accordion(element[0]);
                    accordion.init();
                });
            }
        }
    }]);;
angular
    .module('app')
    .directive('bdplMenu', ['$document', function ($document) {
        return {
            link: function (scope, element, attr) {
                // Currently, it appears that focusing the menu button will activate its default behavior
                // so the focus trap isn't neccessary. Keep code below for reference.

                // This is a bit hacky version of a focus trap, but AngularJS does not really have an
                // event that fires when the DOM is truely finished rendering.
                // Don't forget to inject $document and $timeout

                // $document.ready($timeout(function() {
                //     const focusablesQuery = 'a:not([tabindex="-1"]), button:not([tabindex="-1"]), input:not([tabindex="-1"], select:not([tabindex="-1"])';
                //     $document.find(focusablesQuery);
                // }, 500));


                /**
                 * Menu
                 * 
                 * @param {*} button 
                 */
                function Menu(button) {
                    this.button = button;
                }

                Menu.prototype.init = function () {
                    this.button.setAttribute('aria-haspopup', 'true');
                    this.button.addEventListener('click', this.handleClick.bind(this));
                    this.button.addEventListener('keydown', this.handleKeydown.bind(this));

                    this.boundListener = this.clickListener.bind(this);

                    // Set menu
                    var menu = document.getElementById(this.button.getAttribute('aria-controls'));
                    if (menu) {
                        this.menu = menu;
                        this.menu.hidden = true;
                        this.menuItems = Array.from(menu.querySelectorAll('[role="menuitem"]')); // TODO: Create PopupMenu and move this there
                    }

                    // Set menu items
                    if (this.menuItems) {
                        const menuLength = this.menuItems.length;

                        this.menuItems.forEach((menuItem) => {
                            new MenuItem(menuItem, this).init();
                        });

                        this.firstMenuItem = this.menuItems[0];
                        this.lastMenuItem = this.menuItems[menuLength - 1];
                    }
                }

                Menu.prototype.open = function () {
                    $document[0].addEventListener('click', this.boundListener);
                    this.button.setAttribute('aria-expanded', 'true');
                    this.menu.hidden = false;
                }

                Menu.prototype.close = function () {
                    $document[0].removeEventListener('click', this.boundListener);
                    this.button.setAttribute('aria-expanded', 'false');
                    this.menu.hidden = true;
                }

                Menu.prototype.clickListener = function (e) {
                    const isPartOfButton = this.button.contains(e.target);
                    if (isPartOfButton) return;

                    const isPartOfMenu = this.menu.contains(e.target);
                    if (isPartOfMenu) return;

                    $document[0].removeEventListener('click', this.boundListener);
                    this.button.setAttribute('aria-expanded', 'false');
                    this.menu.hidden = true;
                }

                Menu.prototype.setFocusToFirstItem = function () {
                    this.menuItems[0].focus();
                }

                Menu.prototype.setFocusToLastItem = function () {
                    this.menuItems[this.menuItems.length - 1].focus();
                }

                Menu.prototype.setFocusToPrevItem = function (currentItem) {
                    if (currentItem === this.firstMenuItem) {
                        this.setFocusToLastItem();
                        return;
                    }

                    var index = this.menuItems.indexOf(currentItem)
                    this.menuItems[index - 1].focus();
                }

                Menu.prototype.setFocusToNextItem = function (currentItem) {
                    if (currentItem === this.lastMenuItem) {
                        this.setFocusToFirstItem();
                        return;
                    }
                    var index = this.menuItems.indexOf(currentItem)
                    this.menuItems[index + 1].focus();
                }

                Menu.prototype.handleClick = function (event) {
                    if (this.button.getAttribute('aria-expanded') === 'true') {
                        this.close();
                    } else {
                        this.open();
                        this.setFocusToFirstItem();
                    }
                }

                Menu.prototype.handleKeydown = function (event) {
                    var flag = false;

                    if (event.altKey || event.ctrlKey || event.metaKey) {
                        return;
                    }

                    switch (event.code) {
                        case 'ArrowDown':
                        case 'Enter':
                        case 'Space':
                            this.open();
                            this.setFocusToFirstItem(); // TODO: Create a PopupMenu type and move function there
                            flag = true;
                            break;
                        case 'ArrowUp':
                            this.open();
                            this.setFocusToLastItem(); // TODO: Create a PopupMenu type and move function there
                            flag = true;
                            break;
                        case 'Escape':
                            this.close();
                            break;
                        case 'Tab':
                            this.close();
                            break;
                        default:
                            break;
                    }

                    if (flag) {
                        event.stopPropagation();
                        event.preventDefault();
                    }
                }


                /**
                 * MenuItem
                 * 
                 * @param {*} element 
                 * @param {*} menu 
                 */
                function MenuItem(element, menu) {
                    this.menuItem = element;
                    this.menu = menu;
                }

                MenuItem.prototype.init = function () {
                    this.menuItem.addEventListener('click', this.handleClick.bind(this));
                    this.menuItem.addEventListener('keydown', this.handleKeydown.bind(this));
                }

                MenuItem.prototype.handleClick = function (event) {
                    if (!event.isTrusted) {
                        // From the keyboard. Not supported on IE.
                        // This inadvertently activates Menu.button.click()
                        // which will also close the menu
                        this.menu.button.focus();
                    } else {
                        this.menu.close();
                    }
                }

                MenuItem.prototype.handleKeydown = function (event) {
                    var flag = false; // Prevents browser from scrolling

                    switch (event.code) {
                        case 'Enter':
                            this.menuItem.click(); // This will close the menu. See notes in MenuItem.prototype.handleClick.
                            break;
                        case 'Escape':
                            this.menu.close();
                            this.menu.button.focus();
                            break;
                        case 'ArrowUp':
                        case 'ArrowLeft':
                            this.menu.setFocusToPrevItem(this.menuItem);
                            flag = true;
                            break;
                        case 'ArrowDown':
                        case 'ArrowRight':
                            this.menu.setFocusToNextItem(this.menuItem);
                            flag = true;
                            break;
                        case 'Home':
                            this.menu.setFocusToFirstItem();
                            flag = true;
                            break;
                        case 'End':
                            this.menu.setFocusToLastItem();
                            flag = true;
                            break;
                        case 'Tab':
                            this.menu.close();
                            this.menu.button.focus(); // This will activate default tab behavior
                            break;
                        default:
                            break;

                        // TODO: Implement A-Z, a-z cases
                    }

                    if (flag) {
                        event.stopPropagation();
                        event.preventDefault();
                    }
                }

                const menu = new Menu(element[0]);
                menu.init();
            }
        }
    }]);;
(function () {
	'use strict'
	
	window.bdApp.directive('boxSticky', function () {
		return {
			compile(element) {
				const update = () => {
					const offset = element.parent().offset();
					element.css('top', `${offset.top}px`);
					element.css('position', 'sticky');
				}
				
				window.addEventListener('resize', update);
				
				update();
			}
		}
	})
})();
(function () {
	'use strict';

	angular.module('app')
			.directive('clickOutside', ['$document', '$parse', clickOutside]);

	function clickOutside($document, $parse) {
		return {
			restrict: 'A',
			link: function ($scope, elem, attr) {
				var classList = (attr.outsideIfNot !== undefined) ? attr.outsideIfNot.replace(', ', ',').split(',') : [];

				// add the elements id so it is not counted in the click listening
				if (attr.id !== undefined) {
					classList.push(attr.id);
				}

				var eventHandler = function (e) {

					//check if our element already hiden
					if (angular.element(elem).hasClass("ng-hide")) {
						return;
					}

					var i = 0,
							element;

					// if there is no click target, no point going on
					if (!e || !e.target) {
						return;
					}

					// loop through the available elements, looking for classes in the class list that might match and so will eat
					for (element = e.target; element; element = element.parentNode) {
						var id = element.id,
								classNames = element.className,
								l = classList.length;

						// loop through the elements id's and classnames looking for exceptions
						for (i = 0; i < l; i++) {
							// check for id's or classes, but only if they exist in the first place
							if ((id !== undefined && id.indexOf(classList[i]) > -1) || (classNames && classNames.indexOf(classList[i]) > -1)) {
								// now let's exit out as it is an element that has been defined as being ignored for clicking outside
								return;
							}
						}
					}

					// if we have got this far, then we are good to go with processing the command passed in via the click-outside attribute
					return $scope.$apply(function () {
						return $scope.$eval(attr.clickOutside);
					});
				};

				// assign the document click handler to a variable so we can un-register it when the directive is destroyed
				$document.on('click', eventHandler);

				// when the scope is destroyed, clean up the documents click handler as we don't want it hanging around
				$scope.$on('$destroy', function () {
					$document.off('click', eventHandler);
				});
			}
		};
	}
})();;
(function () {
	'use strict';
	window.bdApp.directive('commonMask', ($timeout) => ({
		scope: false,
		require: 'ngModel',
		link(scope, element, attrs, $ctrl) {
			let mask = attrs['commonMask'];
			element.mask(mask, {
				selectOnFocus: true, autoclear: true, completed() {
					$timeout(() => {
						scope.$apply(() => {
							let value = this.val().toString();
							$ctrl.$setViewValue(value);
							element.val(value);
						});
					});
				}
			});
		}
	}))
})()
;
(function () {
	'use strict';
	
	angular.module('app')
		.directive('displayRoundedQty', ['appUtils', '$filter', function (appUtils, $filter) {
			return {
				restrict: 'A',
				require: '?ngModel',
				link: function (scope, element, attrs, ngModel) {
					
					if (!ngModel)
						return;
					
					var parseNumber = function (value) {
						if (value) {
							if (isNaN(value)) {
								value = value.replace(',', '');
								value = parseFloat(value);
							}
						}
						return value;
					}
					
					var roundNumber = function (value) {
						value = parseNumber(value);
						if (value) {
							return appUtils.round(value)
						}
					}
					
					element.bind('change', function (e) {
						element.val(roundNumber(e.target.value));
					});
					
					// element.bind('blur', function (e) {
					// 	element.val(roundMe(ngModel.$modelValue));
					// });
					
					ngModel.$formatters.push(function (value) {
						if (value) {
							return roundNumber(value);
						}
					});
					
					ngModel.$parsers.push(function (value) {
						if (value) {
							return parseNumber(roundNumber(value));
						}
					});
				}
			};
		}]);
}());
;
(function() {
	'use strict';

	angular.module('app')
		.directive('errSrc', function() {
			return {
				link: function(scope, element, attrs) {
					element.bind('error', function() {
						if (attrs.src != attrs.errSrc) {
							attrs.$set('src', attrs.errSrc);
						}
					});
				}
			}
		});

}());;
(function() {
	'use strict';

	angular.module('app')
		.directive('escKey', function() {
			return function(scope, element, attrs) {
				element.bind('keydown keypress', function(event) {
					if (event.which === 27) { // 27 = esc key
						scope.$apply(function() {
							scope.$eval(attrs.escKey);
						});

						event.preventDefault();
					}
				});
			};
		});
}());;
(function () {
	'use strict';
	window.bdApp.directive('gAutocomplete', ($parse, uiGmapGoogleMapApi) => ({
		scope: false, link(scope, elem, attrs) {
			let callback = ($parse(attrs.gAutocomplete))(scope);
			uiGmapGoogleMapApi.then(maps => {
				let node = elem.get(0);
				scope.component = new maps.places.Autocomplete(node);
				scope.component.addListener('place_changed', () => callback(scope.component));
				attrs.gAutocompleteRestriction && scope.$watch(attrs.gAutocompleteRestriction, (value) => scope.component.setComponentRestrictions({country: [value]}));
			});
		}
	}));
})()
;
(function() {
	'use strict';

	angular.module('app')
		.directive('keepOnscreen', [
			function() {
				return {
					link: function(scope, element, attrs) {

						attrs.$observe('keepOnscreen', function(value) {

							if (value === 'true') {
								
								var popupElement = $(element).parents(attrs.keepOnscreenContainer);
								var selectedElement = $(element);

								if (!selectedElement) return;

								if (selectedElement.position().top < 0) {
									popupElement.scrollTop(popupElement.scrollTop() + selectedElement.position().top);
								} else if (popupElement.height() < selectedElement.position().top + selectedElement.height()) {
									popupElement.scrollTop(popupElement.scrollTop() + (selectedElement.position().top + selectedElement.height() - popupElement.height()));
								}

							}
						});
					}
				};
			}
		]);
}());;
(function () {
	"use strict";
	
	window.bdApp.directive('loadWebContent', function ($http, appSettings, myModuleConst) {
		return {
			replace: true,
			template: `<div ng-bind-html="data"></div>`,
			// templateUrl: appSettings.getUrl(myModuleConst.loadWebContentTemplate),
			scope: {
				show: "=?",
				loadWebUrl: "@",
				contentLoaded: "=?",
				loadWebErrorMessage: "@",
			},
			link: function (scope) {
				if(!scope.show || !scope.show.replace(/\s/g, '')) return;
				let path = scope.loadWebUrl.replace(/\s/g, '');
				let url = appSettings.getSecureUrl(path, true);
				$http.get(url).then(res => {
					if(res.data.match(/title\>.*?404.*?\<\/title/)) throw '404';
					scope.contentLoaded = true;
					scope.data = res.data;
				}).catch(error => {
					scope.data = scope.loadWebErrorMessage;
					scope.contentLoaded = false;
				});
			}
		};
	});
})();
;
(function () {
	'use strict';
	
	window.bdApp.directive('masonry', ($timeout) => ({
		transclude: true,
		compile($element, attrs, linker) {
			let tiles = {};
			
			$element.masonry({
				percentPosition: true,
				horizontalOrder: false,
				columnWidth: '.masonry-item',
				itemSelector: '.masonry-item',
			});
			
			return (scope) => {
				const addTile = (item, last) => {
					let inner = scope.$new(false);
					inner['image'] = item;
					inner['$last'] = last;
					return linker(inner, (clone) => {
						tiles[item.id] = {
							scope: inner,
							element: clone,
							collectionItem: item,
						};
						return $timeout(() => {
							$element.append(clone).masonry('appended', clone).masonry('layout');
							clone.find('img').on('load', function (event) {
								angular.element(event.target).off('load', this);
								$element.masonry('layout');
							});
						});
					});
				};
				
				scope.$on('masonry.clean', () => {
					for (let key in tiles) {
						const item = tiles[key];
						$element.masonry('remove', item.element);
						item.scope.$destroy();
						delete tiles[key];
					}
					$element.masonry('layout');
				});
				
				return scope.$watchCollection(attrs.masonry, (newCollection) => {
					if (!(newCollection != null ? newCollection.length : void 0)) return;
					
					for (const key in tiles) {
						if (!newCollection.some(item => item.id === key)) {
							const item = tiles[key];
							$element.masonry('remove', item.element);
							item.scope.$destroy();
							delete tiles[key];
						}
					}
					
					newCollection.forEach((item, index) => {
						const last = index === newCollection.length - 1;
						if (tiles[item.id]) {
							tiles[item.id].scope.$last = last;
						} else {
							addTile(item, last);
						}
					});
					
					$element.masonry('layout');
				});
			};
		},
	}));
})();
(function () {
	'use strict'

	let template = `
		<div class="bd-search-panel">
			<button class="site-header-menu-button icon-search" ng-click="open()">Search</button>
			<bd-drawer open="data.open">
					<oep-search-with-suggestions-mobile></oep-search-with-suggestions-mobile>
			</bd-drawer>
		</div>
	`;

	window.bdApp.directive('bdSearchBtn', () => ({
		template,
		scope: true,
		replace: true,
		link(scope) {
			scope.data = {open: false};
			scope.open = () => scope.data.open = true;
			scope.close = () => scope.data.open = false;
			scope.toggle = () => scope.data.open = !scope.data.open;
		},
	}));
})()
;
(function () {
	'use strict';
	window.bdApp.directive('ngModelInit', ($timeout) => ({
		scope: false, require: 'ngModel', link: (scope, elem, attrs, $ctrl) => {
			let value = attrs.ngModelInit.toLowerCase() === 'false' ? false : attrs.ngModelInit;
			if (typeof value === 'string') {
				if (value === '' && elem.val() !== '') value = elem.val();
				if (elem.val() === '') elem.val(value);
			}
			$ctrl.$setViewValue(value);
		}
	}));
})()
;
(function () {
	'use strict';

	angular.module('app').directive('ngEnter', ['$timeout', function ($timeout) {
		return function (scope, element, attrs) {
			element.bind("keydown keypress", function (event) {
				var keyCode = event.which || event.keyCode;
				if (keyCode === 13) {

					scope.$apply(function () {
						$timeout(function () {
							scope.$eval(attrs.ngEnter);
						});
					});
					event.preventDefault();

				}
			});
		};
	}]);

})();;
(function () {
	'use strict';
	
	const OepFilter = (appSettings, myModuleConst) => ({
		scope: false,
		replace: true,
		templateUrl: appSettings.getUrl(myModuleConst.oepFilterTemplate),
		compile(elem, attrs) {
			return (scope) => {
				elem.removeAttr('title');
				scope.title = attrs.title;
			}
		}
	})
	
	window.bdApp.directive('oepFilter', OepFilter)
})()
;
(function () {
	'use strict';

	angular.module('app')
		.directive('oepItemsCount',
		[
			'$http', 'spinner', 'appSettings', 'myModuleConst', function ($http, spinner, appSettings, myModuleConst) {

				var url = appSettings.getUrl('home/accountinformation', true);

				return {
					scope: {},
					template: '<a href="{{shoppingBagUrl}}"><span class="bag"><span class="item-count" ng-show="itemsCount > 0"><span class="items">{{itemsCount}}</span></span></span></a>',
					link: function (scope, element, attrs) {

						scope.shoppingBagUrl = appSettings.getUrl('shoppingbag', true);

						scope.itemsCount = 0;

						$http({
							method: 'GET',
							url: url,
							headers: {
								'X-Requested-With': 'XMLHttpRequest'
							}
						})
							.then(function (response) {
								scope.itemsCount = response.data.itemsCount;
							}, function (error) {
								console.log(error);
							});
					}
				};


			}
		]);
}());;
(function () {
	'use strict';

	angular.module('app')
		.directive('oepScroll', [
			'$window', function ($window) {
				return function (scope, element, attrs) {
					var scrollPos = 0;
					angular.element($window).bind('scroll', function () {

						var scrollTop = $(this).scrollTop();
						var delta = scrollPos - scrollTop;

						var action = scrollTop > 0 && delta < 0 ?
						attrs.oepScrollDown :
						attrs.oepScrollUp;

						if (action) {
							scope.$apply(function () {
								scope.$eval(action);
							});
						}

						scrollPos = $(this).scrollTop();
					});
				};
			}
		]);
}());;
(function () {
	'use strict';

	angular.module('app')
		.directive('oepSearch', ['$q', '$http', 'spinner', 'appSettings', 'myModuleConst', '$window', function ($q, $http, spinner, appSettings, myModuleConst, $window) {

			return {
				scope: {},

				templateUrl: appSettings.getUrl(myModuleConst.searchBoxTemplatePath),

				link: function (scope, element, attrs) {
					scope.baseSearchUrl = appSettings.getUrl('product/list/');
					scope.searchUrl = {};
					scope.contentSearchUrl = {};
					scope.model = {
						url: null,
						_criteria: '',
						placeholder: attrs.placeholder,
						clearSearchImg: '//res.cloudinary.com/bedrosians/image/upload/v1/assets/content/icons/small_x.svg'
					}

					scope.clearSearch = function () {
						scope.model._criteria = '';
						scope.data = null;
						scope.data = { urls: [], categories: [], products: [], foundCount: 0, pageFoundCount : 0 };
					}

					scope.getProductListUrl = function (categoryName) {
						return appSettings.getUrl('product/list/' + categoryName + '/?criteria=' + scope.model._criteria, true);
					}

					scope.getProductDetailUrl = function (product) {
						return appSettings.getUrl('product/detail/' + product.UrlFriendlyStyleName + '/?itemNo=' + product.ProductCode, true);
					}

					scope.selectUrl = function (url) {
						scope.model.url = url;
					}

					scope.performSearch = function () {
						$window.location.href = scope.model.url;
					}

					scope.handleKeyDown = function ($event) {
						if (scope.data && scope.data.urls && scope.data.urls.length > 1) {
							switch ($event.keyCode) {
								case 40:
									if (scope.model.url === scope.searchUrl) {
										scope.selectUrl(scope.data.urls[0]);
									} else {
										var down = scope.data.urls.indexOf(scope.model.url);
										down++;

										if (down < scope.data.urls.length) {
											scope.selectUrl(scope.data.urls[down]);
										} else {
											scope.selectUrl(scope.searchUrl);
										}
									}
									break;
								case 38:
									if (scope.model.url === scope.searchUrl) {
										scope.selectUrl(scope.data.urls[scope.data.urls.length - 1]);
									} else {
										var up = scope.data.urls.indexOf(scope.model.url);
										up--;

										if (up < 0) {
											scope.selectUrl(scope.searchUrl);
										} else if (up < scope.data.urls.length) {
											scope.selectUrl(scope.data.urls[up]);
										}
									}
									break;
							}
						}
					};

					scope.canceler = $q.defer();

					scope.pop = function (criteria) {

						scope.data = { urls: [], categories: [], products: [], foundCount: 0, pageFoundCount : 0 };
						scope.model.url = null;

						if (scope.canceler)
							scope.canceler.resolve();
						spinner.endLoad();

						if (criteria && criteria.length >= 1) {
							spinner.startLoad();
							scope.canceler = $q.defer();

							scope.model.url = scope.searchUrl = appSettings.getUrl('product/list/?criteria=' + scope.model._criteria, true);

							var req = {
								method: 'POST',
								url: scope.searchUrl,
								headers: {
									'X-Requested-With': 'XMLHttpRequest'
								},
								timeout: scope.canceler.promise
							}

							var productPromise = $http(req)
								.then(function (response) {
									var data = { urls: [], categories: [], products: [], foundCount: 0 };

									data.foundCount = response.data.foundCount;

									response.data.categories.forEach(function (element) {
										var item = {
											url: scope.getProductListUrl(element.urlName),
											item: element
										};
										data.urls.push(item.url);
										data.categories.push(item);
									});

									response.data.products.forEach(function (element, index) {
										if (index >= 10) return; //TODO: configure
										var item = {
											url: scope.getProductDetailUrl(element),
											item: element
										};
										data.urls.push(item.url);
										data.products.push(item);
									});

									scope.data.urls = data.urls;
									scope.data.categories = data.categories;
									scope.data.products = data.products;
									scope.data.foundCount = data.foundCount;

									spinner.endLoad();
								}, function (error) {
									console.log(error);
								});

							scope.contentSearchUrl = appSettings.getUrl('search/content/?q=' + scope.model._criteria, true);

							var contentPromise = $http({
								method: 'GET',
								url: scope.contentSearchUrl,
								headers: {
									'X-Requested-With': 'XMLHttpRequest'
								},
								timeout: scope.canceler.promise
							}).then(function (response) {
								var data = { pageItems: [], pageFoundCount: 0 };

								data.pageFoundCount = response.data.totalCount;

								response.data.items.forEach(function (element) {
									var item = {
										url: element.url,
										item: element.title
									};
									data.pageItems.push(item);
								});

								scope.data.pageItems = data.pageItems;
								scope.data.pageFoundCount = data.pageFoundCount;

							}, function (error) {
								console.log(error);
							});

							$q.all([productPromise, contentPromise])
								.then(function () {
									if (scope.data.foundCount == 0 && scope.data.pageFoundCount > 0) {
										scope.model.url = scope.contentSearchUrl;
									}
								})
						}

					}
				}
			};

		}]);
}());
;
(function () {
	'use strict';

	angular.module('app')
		.directive('oepSearchAutocomplete', ['$q', '$http', 'spinner', 'appSettings', 'myModuleConst', '$window', function ($q, $http, spinner, appSettings, myModuleConst, $window) {

			return {
				scope: {},

				templateUrl: appSettings.getUrl(myModuleConst.searchAutocompleteTemplatePath),

				link: function (scope, element, attrs) {
					scope.baseSearchUrl = appSettings.getUrl('product/list/');
					scope.searchUrl = {};
					scope.contentSearchUrl = {};
					scope.model = {
						url: null,
						criteria: '',
						placeholder: attrs.placeholder,
						clearSearchImg: '//res.cloudinary.com/bedrosians/image/upload/v1/assets/content/icons/small_x.svg'
					}

					scope.getUrlFromSuggestion = function (suggestion) {
						if (suggestion.category) {
							return appSettings.getUrl('product/list/?criteria=' + suggestion.searchString + '&' + scope.data.categoryFacetName + '=' + suggestion.category, true);
						}
						else {
							return appSettings.getUrl('product/list/?criteria=' + suggestion.searchString, true);
						}
					}

					scope.performSearch = function (url) {
						if (url) {
							$window.location.href = url;
						}
						else {
							const newUrl = appSettings.getUrl('product/list/?criteria=' + $("#js-search-input-box").val(), true);
							$window.location.href = newUrl;
						}
					}

					scope.clearSearch = function () {
						scope.model.criteria = '';
						scope.data = null;
						scope.data = { suggestions: [], foundCount: 0, pageFoundCount: 0, categoryFacetName: "" };
					}

					scope.clearSearch();

					scope.handleKeydown = function ($event) {
						if ($event.keyCode == 13) {
							scope.performSearch();
						}
					}

					scope.getSuggestions = function (request, responseCallback) {
						const searchUrl = appSettings.getUrl('search/querysuggestions/?input=' + request.term, true);

						let canceler = $q.defer();

						var req = {
							method: 'GET',
							url: searchUrl,
							headers: {
								'X-Requested-With': 'XMLHttpRequest'
							},
							timeout: canceler.promise
						};

						var suggestionsPromise = $http(req)
							.then(function (response) {
								let data = { suggestions: [] };
								scope.data.categoryFacetName = response.data.categoryFacetName;

								if (response.data.querySuggestions) {
									response.data.querySuggestions.forEach(function (suggestion) {
										var item = {
											url: scope.getUrlFromSuggestion(suggestion),
											searchString: suggestion.searchString,
											category: suggestion.category
										};
										data.suggestions.push(item);
									});

									scope.data.suggestions = data.suggestions;
								}
								else scope.data.suggestions = [];

								spinner.endLoad();
							}, function (error) {
								console.log(error);
							});

						$q.all([suggestionsPromise])
							.then(function () {
								responseCallback(scope.data.suggestions);
							})
					}

					$("#js-search-input-box").autocomplete({
						minLength: 0,
						source: scope.getSuggestions,
						select: function (event, ui) {

							if (ui.item && ui.item.searchString) {
								$("#js-search-input-box").val(ui.item.searchString);
								const url = scope.getUrlFromSuggestion(ui.item);
								scope.performSearch(url);
							}

							return false;
						},
						focus: function (event, ui) {
							if (ui.item && ui.item.searchString) {
								$("#js-search-input-box").val(ui.item.searchString);

							}

							return false;
						},
					})
						.autocomplete("instance")._renderItem = function (ul, item) {
							return $("<li>")
								.append("<span>" + item.searchString + " in <em>" + item.category + "</em></span>")
								.appendTo(ul);
						};

					$("#js-search-input-box").keydown(scope.handleKeydown);
				}
			};
		}]);
}());
;
(function () {
	'use strict';

	angular.module('app')
		.controller('OepSearchController', ['$scope', '$http', '$timeout', 'appSettings', function ($scope, $http, $timeout, appSettings) {
			$scope.show = false;
			$scope.query = null;
			$scope.products = { items: [], count: 0 };

			$scope.queryChange = () => {
				$scope.show = !!$scope.query;

				if (!$scope.show) return $scope.clearQuery();

				Promise.all([searchSuggestion(), searchProduct(), searchContent()]).then(data => {
					$scope.$apply(() => {
						console.log(data);

						/** Make products */
						$scope.products.count = data[1].length;
						$scope.products.items = data[1].sort((a, b) => a.name < b.name ? -1 : 1).slice(0, 10).map(item => ({
							name: item.Name,
							code: item.ProductCode,
							image: `//res.cloudinary.com/bedrosians/image/upload/f_auto,t_product_150/v1/cdn-bedrosian/assets/products/hiresimages/${item.ImageName}`
						}));
						/** Make products */

					});
				});
			}

			$scope.clearQuery = () => {
				$scope.show = false;
				$scope.query = null;
				$scope.products = { items: [], count: 0 };
			}

			const searchSuggestion = () => {
				var url = appSettings.getUrl('search/querysuggestions/?input=' + $scope.query, true);
				return $http.get(url, {
					headers: {
						'X-Requested-With': 'XMLHttpRequest'
					}
				}).then(response => response.data);
			};

			const searchProduct = () => {
				var url = appSettings.getUrl('product/list/?criteria=' + $scope.query, true);
				return $http.post(url, {
					headers: {
						'X-Requested-With': 'XMLHttpRequest'
					}
				}).then(response => response.data.products);
			}

			const searchContent = () => {
				var url = appSettings.getUrl('search/content/?q=' + $scope.query, true);
				return $http.get(url, {
					headers: {
						'X-Requested-With': 'XMLHttpRequest'
					}
				}).then(response => response.data);
			}
		}])
		.directive('oepSearchPanel', ['$q', '$http', 'spinner', 'appSettings', 'myModuleConst', '$window', function ($q, $http, spinner, appSettings, myModuleConst, $window) {
			return {
				scope: {},
				restrict: 'E',
				templateUrl: appSettings.getUrl(myModuleConst.oepSearchPanel),
				//link: (scope, element, attrs) => {
				//}
				//link: function (scope, element, attrs) {
				//	scope.baseSearchUrl = appSettings.getUrl('product/list/');
				//	scope.searchUrl = {};
				//	scope.contentSearchUrl = {};
				//	scope.suggestionSearchUrl = {};
				//	scope.model = {
				//		url: null,
				//		criteria: '',
				//		placeholder: attrs.placeholder,
				//		clearSearchImg: '//res.cloudinary.com/bedrosians/image/upload/v1/assets/content/icons/small_x.svg'
				//	}

				//	scope.clearSearch = function () {
				//		scope.model.criteria = '';
				//		scope.data = null;
				//		scope.data = { suggestions: [], foundCount: 0, pageFoundCount: 0, categoryFacetName: "" };
				//	}

				//	scope.getUrlFromSuggestion = function (suggestion) {
				//		if (suggestion.category) {
				//			return appSettings.getUrl('product/list/?criteria=' + suggestion.searchString + '&' + scope.data.categoryFacetName + '=' + suggestion.category, true);
				//		}
				//		else {
				//			return appSettings.getUrl('product/list/?criteria=' + suggestion.searchString, true);
				//		}
				//	}

				//	scope.getProductListUrl = function (categoryName) {
				//		return appSettings.getUrl('product/list/' + categoryName + '/?criteria=' + scope.model._criteria, true);
				//	}

				//	scope.getProductDetailUrl = function (product) {
				//		return appSettings.getUrl('product/detail/' + product.UrlFriendlyStyleName + '/?itemNo=' + product.ProductCode, true);
				//	}

				//	scope.selectUrl = function (url) {
				//		scope.model.url = url;
				//	}

				//	scope.performSearch = function (url) {
				//		$window.location.href = url ? url : scope.model.url;
				//	}

				//	scope.handleKeyDown = function ($event) {
				//		switch ($event.keyCode) {
				//			case 40:
				//				if (scope.data.suggestions && scope.data.suggestions.length > 0) {
				//					if (scope.model.url === scope.searchUrl) {
				//						scope.selectUrl(scope.data.suggestions[0]);
				//					} else {
				//						var down = scope.data.suggestions.indexOf(scope.model.url);
				//						down++;

				//						if (down < scope.data.suggestions.length) {
				//							scope.selectUrl(scope.data.suggestions[down]);
				//						} else {
				//							scope.selectUrl(scope.searchUrl);
				//						}
				//					}
				//				}
				//				break;
				//			case 38:
				//				if (scope.data.suggestions && scope.data.suggestions.length > 0) {
				//					if (scope.model.url === scope.searchUrl) {
				//						scope.selectUrl(scope.data.suggestions[scope.data.suggestions.length - 1]);
				//					} else {
				//						var up = scope.data.suggestions.indexOf(scope.model.url);
				//						up--;

				//						if (up < 0) {
				//							scope.selectUrl(scope.searchUrl);
				//						} else if (up < scope.data.suggestions.length) {
				//							scope.selectUrl(scope.data.suggestions[up]);
				//						}
				//					}
				//				}
				//				break;
				//			case 13:
				//				const url = appSettings.getUrl('product/list/?criteria=' + scope.model.criteria, true);
				//				scope.selectUrl(url);
				//				scope.performSearch();
				//		}
				//	};

				//	scope.canceler = $q.defer();

				//	scope.pop = function (criteria) {

				//		scope.data = { suggestions: [], foundCount: 0, pageFoundCount: 0, categoryFacetName: "" };
				//		scope.model.url = null;

				//		if (scope.canceler)
				//			scope.canceler.resolve();
				//		spinner.endLoad();

				//		if (criteria && criteria.length >= 1) {
				//			spinner.startLoad();
				//			scope.canceler = $q.defer();

				//			scope.model.url = scope.searchUrl = appSettings.getUrl('product/list/?criteria=' + scope.model.criteria, true);

				//			var productPromise = $http({
				//				method: 'POST',
				//				url: scope.searchUrl,
				//				headers: {
				//					'X-Requested-With': 'XMLHttpRequest'
				//				},
				//				timeout: scope.canceler.promise
				//			})
				//				.then(function (response) {
				//					var data = { urls: [], categories: [], products: [], foundCount: 0 };

				//					data.foundCount = response.data.foundCount;

				//					response.data.categories.forEach(function (element) {
				//						var item = {
				//							url: scope.getProductListUrl(element.urlName),
				//							item: element
				//						};
				//						data.urls.push(item.url);
				//						data.categories.push(item);
				//					});

				//					response.data.products.splice(0, 10).forEach(function (element, index) {
				//						//if (index >= 10) return; //TODO: configure
				//						var item = {
				//							url: scope.getProductDetailUrl(element),
				//							item: element
				//						};
				//						data.urls.push(item.url);
				//						data.products.push(item);
				//					});

				//					scope.data.urls = data.urls;
				//					scope.data.categories = data.categories;
				//					scope.data.products = data.products;
				//					scope.data.foundCount = data.foundCount;

				//					spinner.endLoad();
				//				}, function (error) {
				//					console.log(error);
				//				});

				//			scope.suggestionSearchUrl = appSettings.getUrl('search/querysuggestions/?input=' + scope.model.criteria, true);

				//			var suggestionsPromise = $http({
				//				method: 'GET',
				//				url: scope.suggestionSearchUrl,
				//				headers: {
				//					'X-Requested-With': 'XMLHttpRequest'
				//				},
				//				timeout: scope.canceler.promise
				//			})
				//				.then(function (response) {
				//					var data = { suggestions: [], foundCount: 0 };

				//					data.foundCount = response.data.foundCount;
				//					scope.data.categoryFacetName = response.data.categoryFacetName;

				//					response.data.querySuggestions.forEach(function (suggestion) {
				//						var item = {
				//							url: scope.getUrlFromSuggestion(suggestion),
				//							searchString: suggestion.searchString,
				//							category: suggestion.category
				//						};
				//						data.suggestions.push(item);
				//					});

				//					scope.data.suggestions = data.suggestions;
				//					scope.data.foundCount = data.foundCount;

				//					spinner.endLoad();
				//				}, function (error) {
				//					console.log(error);
				//				});

				//			scope.contentSearchUrl = appSettings.getUrl('search/content/?q=' + scope.model.criteria, true);

				//			var contentPromise = $http({
				//				method: 'GET',
				//				url: scope.contentSearchUrl,
				//				headers: {
				//					'X-Requested-With': 'XMLHttpRequest'
				//				},
				//				timeout: scope.canceler.promise
				//			}).then(function (response) {
				//				var data = { pageItems: [], pageFoundCount: 0 };

				//				data.pageFoundCount = response.data.totalCount;

				//				response.data.items.slice(0, 3).forEach(function (element) {
				//					var item = {
				//						url: element.url,
				//						title: element.title,
				//						description: element.description
				//					};
				//					data.pageItems.push(item);
				//				});

				//				scope.data.pageItems = data.pageItems;
				//				scope.data.pageFoundCount = data.pageFoundCount;

				//			}, function (error) {
				//				console.log(error);
				//			});

				//			$q.all([productPromise, suggestionsPromise, contentPromise])
				//				.then(function () {
				//					if (scope.data.foundCount == 0 && scope.data.pageFoundCount > 0) {
				//						scope.model.url = scope.contentSearchUrl;
				//					}
				//				})
				//		}

				//		// Calculate correct popup height
				//		var el = $('.site-search-container .popup');
				//		el.css('height', `calc(100vh - ${el.get()[0].offsetTop}px)`);
				//		el.css('overflow', 'auto');
				//	}
				//}
			};

		}]);
}());
;
(function () {
    'use strict';

    angular.module('app')
        .directive('oepSearchWithSuggestions', ['$q', '$http', '$document', 'appSettings', 'myModuleConst', '$window', function ($q, $http, $document, appSettings, myModuleConst, $window) {

            return {
                scope: {},

                templateUrl: appSettings.getUrl(myModuleConst.searchWithSuggestionsTemplatePath),

                link: function (scope, element, attrs) {

                    function getUrlFromSuggestion(suggestion, facet) {
                        var url = suggestion.category ? 'product/list/?criteria=' + suggestion.searchString + '&' + facet + '=' + suggestion.category
                            : 'product/list/?criteria=' + suggestion.searchString;

                        return appSettings.getUrl(url, true);
                    }

                    function createOverlay() {
                        const overlayEl = document.createElement('div');
                        overlayEl.classList.add('search-overlay');
                        overlayEl.hidden = true;
                        return overlayEl;
                    }

                    function SearchBar(view) {
                        this.view = view;
                        this.overlay = createOverlay();
                        this.view.appendChild(this.overlay);
                        // document.body.appendChild(this.overlay);
                        this.searchBar = this.view.querySelector('[role="search"]');
                    }

                    SearchBar.prototype.init = function () {
                        this.boundClickListener = this.handleClick.bind(this);
                        this.boundKeyListener = this.handleKeyDown.bind(this);
                        this.debounced = _.debounce(this.handleChange.bind(this), 500);

                        this.cancelButton = this.searchBar.querySelector('button');
                        this.cancelButton.hidden = true;

                        this.searchBar.addEventListener('click', this.boundClickListener);

                        this.searchForm = this.view.querySelector('form');
                        this.searchForm.setAttribute('action', appSettings.getUrl('product/list/', true));

                        this.searchInput = this.searchBar.querySelector('input[type="search"]');
                        this.searchInput.addEventListener('input', this.debounced);

                        this.searchResults = this.searchBar.querySelector('.site-header-search-results');
                        this.searchResults.ariaExpanded = false;

                        //this.searchSuggestions = document.getElementById('js-search-suggestions');

                        //this.productSearchResults = document.getElementById('js-product-search-results');

                        //this.pageSearchResults = document.getElementById('js-product-page-results');

                        // Animation
                        this.timeline = gsap.timeline({
                            onComplete: () => {
                                this.searchResults.removeAttribute('style');
                            },
                            onReverseComplete: () => {
                                this.overlay.hidden = true;
                                this.clearResults();
                            }
                        });
                        this.timeline.from(this.searchResults, {
                            height: 0,
                            duration: 1,
                        });
                        this.timeline.from(this.overlay, {
                            opacity: 0,
                            duration: 2,
                            ease: 'none',
                        }, '-=1');
                        this.timeline.reverse();
                    }

                    SearchBar.prototype.open = function () {
                        this.cancelButton.hidden = false;
                        this.overlay.hidden = false;
                        this.searchBar.classList.add('site-header-search--active');
                        this.searchBar.removeEventListener('click', this.boundClickListener);
                        this.searchResults.ariaExpanded = true;
                        this.timeline.duration(0.15);
                        this.timeline.play();

                        $document[0].addEventListener('click', this.boundClickListener);
                        $document[0].addEventListener('keydown', this.boundKeyListener);
                    }

                    SearchBar.prototype.close = function () {
                        this.cancelButton.hidden = true;
                        this.searchBar.classList.remove('site-header-search--active');
                        this.searchInput.blur();
                        this.searchInput.value = '';
                        this.searchBar.addEventListener('click', this.boundClickListener);
                        this.searchResults.ariaExpanded = false;
                        this.timeline.duration(0.1);
                        this.timeline.reverse();
                        this.clearResults();

                        $document[0].removeEventListener('click', this.boundClickListener);
                        $document[0].removeEventListener('keydown', this.boundKeyListener);
                    }

                    SearchBar.prototype.clearResults = function () {
                        scope.$apply(() => {
                            scope.notFound = false;
                            scope.pages = {totalCount: 0};
                            scope.products = {foundCount: 0};
                            scope.suggestions = {foundCount: 0};
                        })
                    }

                    SearchBar.prototype.fetchResults = async function (value) {

                        if (!value) return;

                        const headers = {'X-Requested-With': 'XMLHttpRequest'}

                        scope.$apply(() => {
                            scope.loading = true;
                            scope.pageResultsUrl = appSettings.getUrl('search/content/?q=' + value, true);
                            scope.suggestionResultsUrl = appSettings.getUrl('search/querysuggestions/?input=' + value, true);
                            scope.productResultsUrl = appSettings.getUrl('product/list/?criteria=' + value + '&storeNavInfo=false', true);
                        });

                        const pages = await $http({url: scope.pageResultsUrl, headers: headers})
                            .then(res => res.data)
                            .catch(e => console.error(e));

                        const products = await $http({url: scope.productResultsUrl, headers: headers})
                            .then(res => res.data)
                            .catch(e => console.error(e));

                        const suggestions = await $http({url: scope.suggestionResultsUrl, headers: headers})
                            .then(res => res.data)
                            .catch(e => console.error(e));

                        return {pages, products, suggestions};
                    }

                    SearchBar.prototype.handleChange = function (e) {
                        const inputValue = e.target.value;

                        if (!inputValue) {
                            // TODO: Set loading to false
                            this.clearResults();
                            return;
                        }

                        this.fetchResults(inputValue)
                            .then(res => {
                                scope.$apply(() => {
                                    scope.loading = false;

                                    if (!res.suggestions && !res.products && !res.pages) {
                                        scope.notFound = true;
                                        return;
                                    }

                                    if (res.suggestions)
                                        scope.suggestions = {
                                            ...res.suggestions,
                                            querySuggestions: res.suggestions.querySuggestions.map(
                                                item => (item.url = getUrlFromSuggestion(item, res.suggestions.categoryFacetName), item)
                                            )
                                        };

                                    if (res.products)
                                        scope.products = {
                                            ...res.products,
                                            products: res.products.products.slice(0, 10).map(
                                                item => (item.url = appSettings.getUrl('product/detail/' + item.UrlFriendlyStyleName + '/?itemNo=' + item.ProductCode, true), item)
                                            )
                                        };

                                    if (res.pages)
                                        scope.pages = res.pages;
                                });
                            })
                            .catch(e => console.error(e))
                    }

                    SearchBar.prototype.handleClick = function (e) {
                        e.stopPropagation();

                        const isCancelButton = this.cancelButton.contains(e.target);
                        const isPartOfSearchBar = this.searchBar.contains(e.target);

                        if (isPartOfSearchBar && !isCancelButton) {
                            this.open();
                        } else {
                            this.close();
                        }
                    }

                    SearchBar.prototype.handleKeyDown = function (e) {
                        if (e.key === 'Escape') {
                            console.log('key', e.key);
                            e.preventDefault();
                            this.close();
                        }
                    }

                    const searchBar = new SearchBar(element[0]);

                    searchBar.init();
                }
            };

        }]);
}());
;
(function () {
	'use strict';

	window.bdApp.directive('oepSearchWithSuggestionsMobile', ['appSettings', 'myModuleConst', function (settings, constants) {
		return {
			scope: true,
			controller: 'SearchController',
			templateUrl: settings.getUrl(constants.searchWithSuggestionsMobileTemplatePath),
		};
	}]);
}());
;
(function () {
	'use strict';

	window.bdApp.directive('paymentActions', ($parse) => ({
		scope: false, link(scope, elem, attrs) {
			if (!attrs.paymentActionsWatch) return;
			let actions = ($parse(attrs.paymentActions))(scope);
			scope.$watch(attrs.paymentActionsWatch, (value) => {
				if(!value) return;
				let action = Object.entries(actions).find(([key]) => key === value)[1];
				elem.attr('action', action);
			});
		}
	}))
})()
;
(function () {
	"use strict";

	angular.module('app')
		.directive('selectLocation', ['$rootScope', 'buildversion', 'appSettings', 'ngDialog', '$http', 'branchLocatorService', selectLocation]);

	function selectLocation($rootScope, buildversion, appSettings, ngDialog, $http, branchLocatorService) {
		return {
			restrict: 'E',
			templateUrl: appSettings.getUrl("scripts/app/common/directives/selectLocation.html" + `?v=${buildversion}`),
			scope: {},
			link: function ($scope, element, attrs) {

				$scope.$on('branchChanged', function (event, branch) {
					if (attrs.locationChanged) {
						$scope.$parent.$eval(attrs.locationChanged);
					}
				});

				$scope.data = {
					locations: [],
					busy: false,
					ourLocationsUrl: appSettings.getUrl("our-locations/", true)
				};

				$scope.chooseIt = function (locationCode) {
					$scope.data.busy = true;

					branchLocatorService.ChooseBranchByCode(locationCode, function (response) {
						if (response.data.success) {
							$scope.selectLocationDialog.close(true);
							if (attrs.locationChanged) {
								$scope.$parent.$eval(attrs.locationChanged);
							}
							$scope.data.busy = false;

							var branch = {
								branchState: response.data.context.BranchState,
								branchCity: response.data.context.BranchCity,
								branchCode: response.data.context.BranchCode
							}

							$rootScope.$broadcast('branchChanged', branch);
						} else {
							$scope.data.busy = false;
							alert(response.data.message);
						}
					});
				};

				$scope.selectIt = function () {

					$scope.data.locations = [];

					$scope.selectLocationDialog = ngDialog.open({
						template: appSettings.getUrl("scripts/app/common/directives/selectLocation.dialog.html"),
						className: '',
						scope: $scope,
						showClose: false,
						controller: [
							'$scope', '$http', function ($scope, $http) {

								$scope.data.busy = true;

								$http.get(appSettings.getUrl('our-locations/', true))
									.then(function (response) {
										$scope.data.locations = response.data;
										$scope.data.busy = false;
									}, function (response) {
										$scope.data.busy = false;
									});
							}
						]
					});
				};

			}
		};
	}
})();
;
(function () {
	"use strict";

	angular.module('app')
		.directive('selectState', ['$rootScope', 'buildversion', 'appSettings', 'ngDialog', '$http', 'branchLocatorService', selectState]);

	function selectState($rootScope, buildversion, appSettings, ngDialog, $http, branchLocatorService) {
		return {
			restrict: 'E',
			templateUrl: appSettings.getUrl("scripts/app/common/directives/selectState.html" + `?v=${buildversion}`),
			scope: {},
			link: function ($scope, element, attrs) {

				//$scope.$on('branchChanged', function (event, branch) {
				//	if (attrs.locationChanged) {
				//		$scope.$parent.$eval(attrs.locationChanged);
				//	}
				//});

				$scope.data = {
					states: [],
					busy: false,
					ourStatesUrl: appSettings.getUrl("home/GetAllStates/", true)
				};

				//$scope.chooseIt = function (locationCode) {
				//	$scope.data.busy = true;

				//	branchLocatorService.ChooseBranchByCode(locationCode, function (response) {
				//		if (response.data.success) {
				//			$scope.selectStateDialog.close(true);
				//			if (attrs.locationChanged) {
				//				$scope.$parent.$eval(attrs.locationChanged);
				//			}
				//			$scope.data.busy = false;

				//			var branch = {
				//				branchState: response.data.context.BranchState,
				//				branchCity: response.data.context.BranchCity,
				//				branchCode: response.data.context.BranchCode
				//			}

				//			$rootScope.$broadcast('branchChanged', branch);
				//		} else {
				//			$scope.data.busy = false;
				//			alert(response.data.message);
				//		}
				//	});
				//};

				$scope.selectState = function () {

					$scope.data.states = [];

					$scope.selectStateDialog = ngDialog.open({
						template: appSettings.getUrl("scripts/app/common/directives/selectState.dialog.html"),
						className: '',
						scope: $scope,
						controller: [
							'$scope', '$http', function ($scope, $http) {

								$scope.data.busy = true;

								$http.get(appSettings.getUrl('home/GetAllStates', true))
									.then(function (response) {
										$scope.data.states = response.data;
										$scope.data.busy = false;
									}, function (response) {
										$scope.data.busy = false;
									});
							}
						]
					});
				};

			}
		};
	}
})();
;
(function () {
	'use strict';
	
	angular.module('app')
		.directive('shareButtons', ['appSettings', 'myModuleConst', function (appSettings, myModuleConst) {
			return {
				restrict: 'E',
				scope: {
					shareUrl: '=shareUrl',
					providers: '=providers',
					shareTitle: '=shareTitle',
					shareMedia: '=shareMedia',
				},
				templateUrl: appSettings.getUrl(myModuleConst.shareButtonsPath, false)
			};
		}]);
}());;
(function() {
	"use strict";

	angular.module('app')
		.directive('stickyHeader', ['$window', StickyHeaderDirective]);

	function StickyHeaderDirective($window) {
		return {
			scope: {
				headerOffsetClass: '@',
				stickyClass: '@'
			},
			restrict: 'A',
			link: link
		};

		function link(scope, element, attrs) {
			var body = element.closest('body');
			var stickyClass = scope.stickyClass || 'sticky';
			var topOffsetClass = '.' + scope.headerOffsetClass || 'body';

			var elementTopPosition = element.position().top;
			var headerOffset = body.find(topOffsetClass).outerHeight(true);
			
			element.css("width", element.parent().width());

			angular.element($window).bind('resize',
				function() {
					element.css("width", element.parent().width());
					elementTopPosition = element.parent().position().top;
					headerOffset = body.find(topOffsetClass).outerHeight(true);
					scope.$digest();
				});

			angular.element($window).bind('scroll',
				function() {
					if ($(this).scrollTop() > elementTopPosition - headerOffset) {
						element.addClass(stickyClass).css("padding-top", headerOffset);
						element.parent().css("padding-top", element.height());
					} else {
						element.removeClass(stickyClass).css("padding-top", 0);
						element.parent().css("padding-top", 0);
					}
					scope.$digest();
				});
		}
	}
}());;
(function () {
	'use strict';
	
	window.bdApp.directive('stringToNumber', function() {
		return {
			require: 'ngModel',
			link: function(scope, element, attrs, ngModel) {
				ngModel.$parsers.push(function(value) {
					return '' + value;
				});
				ngModel.$formatters.push(function(value) {
					return parseFloat(value);
				});
			}
		};
	});
})();
(function() {
	'use strict';

	angular.module('app')
		.directive('zoomImage', function() {
			return {
				restrict: 'A',
				link: function(scope, element, attrs) {

					attrs.$observe('zoomImage', function() {
						linkJqueryZoom();
					});

					function linkJqueryZoom() {
						if (!attrs.zoomImage) return;
						var targetContainer = $(attrs.zoomImageTarget);

						yepnope({
							load: ['//res.cloudinary.com/bedrosians/raw/upload/v1437083948/assets/common/jquery.zoom.min.js'],
							complete: function() {
								$(element).zoom({
									magnify: 1,
									url: attrs.zoomImage,
									target: targetContainer,
									onZoomIn: function() {
										targetContainer.show();
									},
									onZoomOut: function() {
										targetContainer.hide();
									}
								});
							}
						});
					}

					linkJqueryZoom();
				}
			};
		});

}());;
(function () {
	'use strict';

	// window.bdApp.service('$cloudinaryCounter', function () {
	// 	let counter = 0;
	// 	return {
	// 		get: () => counter,
	// 		inc: () => counter++,
	// 		reset: () => counter = 0,
	// 	}
	// });

	window.bdApp.filter('cloudinaryUp', function (CloudinaryService, $cloudinaryCounter) {
		return function (input, ...params) {
			let publicId, transformations, raw_transformation;
			try {
				let count = $cloudinaryCounter.get();

				if (count === 9) $cloudinaryCounter.reset();
				else $cloudinaryCounter.inc();

				$.cloudinary.config({
					secure: true,
					cloud_name: 'bedrosians',
					secure_distribution: `res.cloudinary.com`
				});

				if (typeof input === 'string' && /[https?]*:?\/\/.*$/.test(input)) {
					publicId = CloudinaryService.getPublicId(input);
					raw_transformation = CloudinaryService.getTransformations(input);
				}

				if (!publicId) publicId = input;
				if (typeof params[0] === 'object') transformations = params[0];
				else if (params.length > 0) raw_transformation = params.join(',');
				if (params.length > 1) raw_transformation = params.slice(1).join(',');
				return $.cloudinary.url(publicId, {...transformations, raw_transformation});
			} catch (e) {
				console.error(e);
				return input;
			}
		}
	})
})();
(function () {
	'use strict';
	
	window.bdApp.service('$cloudinaryCounter', function () {
		let counter = 0;
		return {
			get: () => counter,
			inc: () => counter++,
			reset: () => counter = 0,
		}
	});
	
	window.bdApp.filter('cloudinary', function($cloudinaryCounter) {
		return function (input) {
			let count = $cloudinaryCounter.get();
			
			if(count === 9) $cloudinaryCounter.reset();
			else $cloudinaryCounter.inc();
			
			return input.replace(/(res).*(cloudinary)/g, `res-${count}.cloudinary`);
		}
	})
})();
(function () {
	'use strict';
	
	const md5 = (d) => { var r = M(V(Y(X(d), 8 * d.length))); return r.toLowerCase(); }; function M(d) { for (var _, m = '0123456789ABCDEF', f = '', r = 0; r < d.length; r++) (_ = d.charCodeAt(r)), (f += m.charAt((_ >>> 4) & 15) + m.charAt(15 & _)); return f; } function X(d) { for (var _ = Array(d.length >> 2), m = 0; m < _.length; m++) _[m] = 0; for (m = 0; m < 8 * d.length; m += 8) _[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32; return _; } function V(d) { for (var _ = '', m = 0; m < 32 * d.length; m += 8) _ += String.fromCharCode((d[m >> 5] >>> m % 32) & 255); return _; } function Y(d, _) { (d[_ >> 5] |= 128 << _ % 32), (d[14 + (((_ + 64) >>> 9) << 4)] = _); for (var m = 1732584193, f = -271733879, r = -1732584194, i = 271733878, n = 0; n < d.length; n += 16) { var h = m, t = f, g = r, e = i; (f = md5_ii( (f = md5_ii( (f = md5_ii( (f = md5_ii( (f = md5_hh( (f = md5_hh( (f = md5_hh( (f = md5_hh( (f = md5_gg( (f = md5_gg( (f = md5_gg( (f = md5_gg( (f = md5_ff( (f = md5_ff( (f = md5_ff( (f = md5_ff( f, (r = md5_ff( r, (i = md5_ff( i, (m = md5_ff(m, f, r, i, d[n + 0], 7, -680876936)), f, r, d[n + 1], 12, -389564586, )), m, f, d[n + 2], 17, 606105819, )), i, m, d[n + 3], 22, -1044525330, )), (r = md5_ff( r, (i = md5_ff( i, (m = md5_ff(m, f, r, i, d[n + 4], 7, -176418897)), f, r, d[n + 5], 12, 1200080426, )), m, f, d[n + 6], 17, -1473231341, )), i, m, d[n + 7], 22, -45705983, )), (r = md5_ff( r, (i = md5_ff( i, (m = md5_ff(m, f, r, i, d[n + 8], 7, 1770035416)), f, r, d[n + 9], 12, -1958414417, )), m, f, d[n + 10], 17, -42063, )), i, m, d[n + 11], 22, -1990404162, )), (r = md5_ff( r, (i = md5_ff( i, (m = md5_ff(m, f, r, i, d[n + 12], 7, 1804603682)), f, r, d[n + 13], 12, -40341101, )), m, f, d[n + 14], 17, -1502002290, )), i, m, d[n + 15], 22, 1236535329, )), (r = md5_gg( r, (i = md5_gg(i, (m = md5_gg(m, f, r, i, d[n + 1], 5, -165796510)), f, r, d[n + 6], 9, -1069501632)), m, f, d[n + 11], 14, 643717713, )), i, m, d[n + 0], 20, -373897302, )), (r = md5_gg( r, (i = md5_gg(i, (m = md5_gg(m, f, r, i, d[n + 5], 5, -701558691)), f, r, d[n + 10], 9, 38016083)), m, f, d[n + 15], 14, -660478335, )), i, m, d[n + 4], 20, -405537848, )), (r = md5_gg( r, (i = md5_gg(i, (m = md5_gg(m, f, r, i, d[n + 9], 5, 568446438)), f, r, d[n + 14], 9, -1019803690)), m, f, d[n + 3], 14, -187363961, )), i, m, d[n + 8], 20, 1163531501, )), (r = md5_gg( r, (i = md5_gg(i, (m = md5_gg(m, f, r, i, d[n + 13], 5, -1444681467)), f, r, d[n + 2], 9, -51403784)), m, f, d[n + 7], 14, 1735328473, )), i, m, d[n + 12], 20, -1926607734, )), (r = md5_hh( r, (i = md5_hh(i, (m = md5_hh(m, f, r, i, d[n + 5], 4, -378558)), f, r, d[n + 8], 11, -2022574463)), m, f, d[n + 11], 16, 1839030562, )), i, m, d[n + 14], 23, -35309556, )), (r = md5_hh( r, (i = md5_hh(i, (m = md5_hh(m, f, r, i, d[n + 1], 4, -1530992060)), f, r, d[n + 4], 11, 1272893353)), m, f, d[n + 7], 16, -155497632, )), i, m, d[n + 10], 23, -1094730640, )), (r = md5_hh( r, (i = md5_hh(i, (m = md5_hh(m, f, r, i, d[n + 13], 4, 681279174)), f, r, d[n + 0], 11, -358537222)), m, f, d[n + 3], 16, -722521979, )), i, m, d[n + 6], 23, 76029189, )), (r = md5_hh( r, (i = md5_hh(i, (m = md5_hh(m, f, r, i, d[n + 9], 4, -640364487)), f, r, d[n + 12], 11, -421815835)), m, f, d[n + 15], 16, 530742520, )), i, m, d[n + 2], 23, -995338651, )), (r = md5_ii( r, (i = md5_ii(i, (m = md5_ii(m, f, r, i, d[n + 0], 6, -198630844)), f, r, d[n + 7], 10, 1126891415)), m, f, d[n + 14], 15, -1416354905, )), i, m, d[n + 5], 21, -57434055, )), (r = md5_ii( r, (i = md5_ii(i, (m = md5_ii(m, f, r, i, d[n + 12], 6, 1700485571)), f, r, d[n + 3], 10, -1894986606)), m, f, d[n + 10], 15, -1051523, )), i, m, d[n + 1], 21, -2054922799, )), (r = md5_ii( r, (i = md5_ii(i, (m = md5_ii(m, f, r, i, d[n + 8], 6, 1873313359)), f, r, d[n + 15], 10, -30611744)), m, f, d[n + 6], 15, -1560198380, )), i, m, d[n + 13], 21, 1309151649, )), (r = md5_ii( r, (i = md5_ii(i, (m = md5_ii(m, f, r, i, d[n + 4], 6, -145523070)), f, r, d[n + 11], 10, -1120210379)), m, f, d[n + 2], 15, 718787259, )), i, m, d[n + 9], 21, -343485551, )), (m = safe_add(m, h)), (f = safe_add(f, t)), (r = safe_add(r, g)), (i = safe_add(i, e)); } return Array(m, f, r, i); } function md5_cmn(d, _, m, f, r, i) { return safe_add(bit_rol(safe_add(safe_add(_, d), safe_add(f, i)), r), m); } function md5_ff(d, _, m, f, r, i, n) { return md5_cmn((_ & m) | (~_ & f), d, _, r, i, n); } function md5_gg(d, _, m, f, r, i, n) { return md5_cmn((_ & f) | (m & ~f), d, _, r, i, n); } function md5_hh(d, _, m, f, r, i, n) { return md5_cmn(_ ^ m ^ f, d, _, r, i, n); } function md5_ii(d, _, m, f, r, i, n) { return md5_cmn(m ^ (_ | ~f), d, _, r, i, n); } function safe_add(d, _) { var m = (65535 & d) + (65535 & _); return (((d >> 16) + (_ >> 16) + (m >> 16)) << 16) | (65535 & m); } function bit_rol(d, _) { return (d << _) | (d >>> (32 - _)); }
	
	window.bdApp.filter('md5', function() {
		return function (input) {
			return md5(input);
		}
	})
})();
(function () {
	"use strict";
	
	window.bdApp.factory("$bannerStore", () => {
		let store = [];
		
		return {
			set: (banners) => store = banners,
			get: () => store,
		}
	})
	
	window.bdApp.service("$bannerService", function ($api, $compile, $location, $bannerStore) {
		return {
			reload:  async () => {
				let data = {
					url: window.location.pathname,
					query: window.location.search.replace(/\?/i, '')
				};
				
				return await $api.$banner.list(data).then((result) => {
					let value = result.value;
					
					let store = $bannerStore.get();
					
					let banners = (store.length === 0) ? result.value : (store.map(x => {
						let $index = value.findIndex(y => x.zone.toLowerCase() === y.zone.toLowerCase());
						return ($index !== -1) ? value[$index] : {...x, content: ''};
					}));
					
					banners = [...banners, ...value.filter(x => !banners.some(y => y.zone.toLowerCase() === x.zone.toLowerCase()))]
					
					$bannerStore.set(banners);
					
					banners.map(banner => {
						let element = angular.element(document.getElementById(`b${banner.zone}`));
						if (element[0]) element.html($compile(banner.content)(element.scope()));
					});
				})
			}
		};
	})
})()
;
(function () {
	'use strict';

	angular.module('app')
	.service('branchLocatorService', ["$http", 'appSettings', function ($http, appSettings) {

		this.GetlocationWasGeoLocated = function () {
			var result = localStorage.getItem("locationWasGeoLocated");
			return result === "true";
		};

		this.SetLocationWasGeoLocated = function () {
			localStorage.setItem("locationWasGeoLocated", "true");
		};

		this.ChooseBranchByCode = function (branchCode, callback) {
			var req = {
				method: 'POST',
				url: appSettings.getUrl("shipping/changeLocation/" + branchCode, true),
				headers: {
					'X-Requested-With': 'XMLHttpRequest'
				}
			};

			$http(req)
				.then(function (response) {
					callback(response);
				});
		};

		this.ChooseStateByAbbreviation = function (stateCode) {

			var url = appSettings.getUrl("shipping/changestatelocation/" + stateCode, true);

			return $http.post(url);
		};

		this.GetStateNameLocated = function () {
			return localStorage.getItem("stateNameWasLocated");
		};

		this.SetStateNameLocated = function (statename) {
			localStorage.setItem("stateNameWasLocated", statename);
		};
		
		this.GetShippingStateName = function () {
			return localStorage.getItem("shippingStateName");
		};
		
		this.SetShippingStateName = function (state) {
			localStorage.setItem("shippingStateName", state);
		};
		
		this.GetShippingCountryName = function () {
			return localStorage.getItem("shippingCountryName");
		};
		
		this.SetShippingCountryName = function (country) {
			localStorage.setItem("shippingCountryName", country);
		};

	}]);
})();
;
(function () {
	'use strict';

	const REGEX_VERSION = /\/v\d+\//;
	const REGEX_FORMAT = /\.(ai|avif|gif|png|webp|bmp|bw|djvu|dng|ps|ept|eps|eps3|fbx|flif|gif|glb|gltf|heif|heic|ico|indd|jpg|jpe|jpeg|jp2|wdp|jxr|hdp|obj|pdf|ply|png|psd|arw|cr2|svg|tga|tif|tiff|u3ma|usdz|webp|3g2|3gp|avi|flv|m3u8|ts|m2ts|mts|mov|mkv|mp4|mpeg|mpd|mxf|ogv|webm|wmv)$/i
	const REGEX_URL = /(https?:)?\/\/(?<host>[^\/]+)\/(?<cloudName>[^\/]+)\/(?<assetType>image|images|video|videos|raw|files)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)?\/?(?<signature>s--([a-zA-Z0-9\_\-]{8}|[a-zA-Z0-9\_\-]{32})--)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?\/?)*\/)*(?<version>v\d+|\w{1,2})\/(?<publicId>[^\s]+)$/;
	const ASSET_TYPES_SEO = ['images', 'videos', 'files'];

	function CloudinaryService() {
		function parseUrl(src) {

			src = encodeURI(src);

			if (typeof src !== 'string') {
				throw new Error(`Failed to parse URL: Invalid src of type ${typeof src}`);
			}

			const hasVersion = REGEX_VERSION.test(src);

			if (!hasVersion) {
				const parts = src.split('/upload/');
				src = `${parts[0]}/upload/v1/${parts[1]}`;
			}

			const [baseUrlWithExtension, queryString] = src.split('?');

			const format = getFormat(baseUrlWithExtension);

			let baseUrl = baseUrlWithExtension;

			if (format) {
				baseUrl = baseUrlWithExtension.replace(new RegExp(`${format}$`), '');
			}

			const results = baseUrl.match(REGEX_URL);

			const transformations = (results.groups.transformations) && results.groups.transformations.split('/').filter(t => !!t);

			const parts = {
				...results.groups,
				format,
				seoSuffix: undefined,
				transformations: transformations || [],
				queryParams: {},
				version: results.groups.version ? parseInt(results.groups.version.replace('v', '')) : undefined
			}

			if (queryString) {
				parts.queryParams = queryString.split('&').reduce((prev, curr) => {
					const [key, value] = curr.split('=');
					prev[key] = value;
					return prev;
				}, {});
			}

			if (parts.assetType && ASSET_TYPES_SEO.includes(parts.assetType)) {
				const publicIdParts = parts.publicId.split('/') || [];
				parts.seoSuffix = publicIdParts.pop();
				parts.publicId = publicIdParts.join('/');
			}

			// The URL Gen SDK which this library relies on will re-encode the public ID. To avoid issues where
			// someone is already passing in a URL or ID that's been encoded programmatically, first decode
			// the public ID, which should theoretically be harmless since it ends up getting encoded

			if (parts.publicId) {
				parts.publicId = decodeURIComponent(parts.publicId);
			}

			return parts;
		}

		/**
		 * getPublicId
		 * @description Retrieves the public id of a Cloudinary image url. If no url is recognized it returns the parameter it self.
		 * If it's recognized that is a url and it's not possible to get the public id, it warns the user.
		 * @param {string} src: The Cloudinary url or public id.
		 */
		function getPublicId(src) {
			const {publicId} = parseUrl(src) || {};
			return publicId;
		}

		/**
		 * getTransformations
		 * @description Retrieves the transformations added to a Cloudinary image url. If no transformation is recognized it returns an empty array.
		 * @param {string} src: The Cloudinary url
		 */
		function getTransformations(src) {
			const {transformations = []} = parseUrl(src) || {};
			return transformations.map(t => t.split(','));
		}

		/**
		 * getFormat
		 * @description Retrieves the format of a given string
		 * @param {string} src: The Cloudinary url or any string trying to match the format
		 */
		function getFormat(src) {
			const matches = src.match(REGEX_FORMAT);
			if (matches === null) return;
			return matches[0];
		}

		/**
		 * normalizeNumberParameter
		 * @description Returns a number given a string or number value
		 * @param {string|number} param: The value to return as a number
		 */
		function normalizeNumberParameter(param) {
			if (typeof param !== 'string') return param;
			return parseInt(param)
		}

		return {
			getFormat,
			getPublicId,
			getTransformations,
		}
	}

	window.bdApp.service('CloudinaryService', [CloudinaryService]);
})();
;
(function () {
	'use strict';

	function CommonService() {

		function getParameterByName(name, url) {
			if (!url) url = window.location.href;
			name = name.replace(/[\[\]]/g, "\\$&");
			var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
				results = regex.exec(url);
			if (!results) return null;
			if (!results[2]) return '';
			return decodeURIComponent(results[2].replace(/\+/g, " "));
		}

		function parseUrl(url) {
			if (!url) url = window.location.href;
			var parser = document.createElement('a');
			parser.href = url;

			return parser;
		}

		return {
			getParameterByName: getParameterByName,
			parseUrl: parseUrl
		};
	}

	angular.module('app').service('CommonService', [CommonService]);
})();
;
(function () {
	'use strict';

	window.bdApp.service('oepFilterService', function ($timeout, $rootScope, $location) {
		$rootScope.oep = {
			filter: {
				busy: true,
				show: false,
				filters: null,
				selected: null,
				refinements: null,
			}
		};

		this.onChangedCallback = null;
		this.previousRefinements = null;

		this.onChanged = (callback) => this.onChangedCallback = callback;

		this.setRefinements = (refinements) => {
			try {
				if (typeof refinements === 'function') refinements = refinements();
				if (angular.equals(refinements, this.previousRefinements)) return;
				this.previousRefinements = refinements;
				$rootScope.oep.filter.refinements = refinements.map(ref => {
					let max = ref.options.length;
					let key = `f_${ref.key}`;
					let expanded = ref.options.some(x => x.selected);
					let min = max > 5 ? (max > 10 ? 5 : 10) : max;
					let show = expanded ? max : min;
					return ({
						...ref,
						key,
						min,
						max,
						show,
						expanded,
						hasMore: min < max,
					});
				});
			} catch (error) {
				console.error('Error setting refinements:', error);
			}
		};

		this.getFilters = () => {
			try {
				return $rootScope.oep.filter.refinements.reduce((acc, item) => {
					let selected = item.options.filter(x => x.selected).map(x => encodeURI(x.value));
					if (selected.length > 0) acc[item.key] = selected.join(',');
					return acc;
				}, {});
			} catch (error) {
				console.error('Error getting filters:', error);
				return {};
			}
		};

		this.getSelected = () => {
			try {
				return $rootScope.oep.filter.refinements.reduce((acc, item) => {
					item.options.filter(x => x.selected).map(x => acc.push(x));
					return acc;
				}, []);
			} catch (error) {
				console.error('Error getting selected options:', error);
				return [];
			}
		};

		$rootScope.$watch('oep.filter.refinements', () => {
			if (!$rootScope.oep.filter.refinements) return;
			$rootScope.oep.filter.filters = this.getFilters();
			$rootScope.oep.filter.selected = this.getSelected();
		}, true);

		$rootScope.$watch('oep.filter.show', (value) => {
			let body = $('body');
			let search = $location.search();
			if (value) {
				let padding = window.innerWidth - body.innerWidth();
				body.css('padding-right', `${padding}px`);
				body.addClass('ngdialog-open');
				if ($rootScope.oep.filter.track)
					$location.search({
						...search,
						showFacetPanel: 'true'
					});
			} else {
				body.css('padding-right', '');
				body.removeClass('ngdialog-open');
				if ($rootScope.oep.filter.track)
					$location.search({
						...search,
						showFacetPanel: undefined,
					});
			}
		});

		$rootScope.$watch('oep.filter.filters', (newValue, oldValue) => {
			if (!newValue || angular.equals(newValue, oldValue)) return;
			$rootScope.$emit('oep.filter.apply');
		});

		$rootScope.$on('oep.filter.apply', () => {
			if (this.onChangedCallback) {
				this.onChangedCallback($rootScope.oep.filter.filters);
			}
		});

		$rootScope.$on('oep.filter.reset', () => {
			for (let filter of $rootScope.oep.filter.refinements)
				for (let option of filter.options) option.selected = false;
		});

		$rootScope.$on('oep.filter.busy', () => $rootScope.oep.filter.busy = true);
		$rootScope.$on('oep.filter.ready', () => $rootScope.oep.filter.busy = false);

		$rootScope.$on('oep.filter.show', () => $rootScope.oep.filter.show = true);
		$rootScope.$on('oep.filter.close', () => $rootScope.oep.filter.show = false);
		$rootScope.$on('oep.filter.toggle', () => $rootScope.oep.filter.show = !$rootScope.oep.filter.show);

		$rootScope.$on('oep.filter.refinement.toggle', (e, refinement) => {
			refinement.expanded = !refinement.expanded;
			refinement.show = (refinement.expanded) ? refinement.max : refinement.min;
		});

		this.init = function (track = true) {
			$rootScope.oep.filter.track = track;
			if (track) {
				let opened = $location.search().showFacetPanel;
				if (opened && opened === 'true') $rootScope.$emit('oep.filter.show');
			}
		}
	});
})();
;
(function () {
	'use strict';

	angular.module('app')
		.service('googleTagManagerService', ['$window', function ($window) {
			$window.dataLayer = $window.dataLayer || [];

			this.ItemAddedEvent = function (itemNo, itemQty, itemQtyUom, itemAmount, itemAmountCurrency, eventId, addEcommerce) {
				if ($window.isProfessional === true) return;

				const itemAmount2Decimals = parseFloat(itemAmount).toFixed(2);

				$window.dataLayer.push({
					"itemNo": itemNo,
					"itemQty": itemQty,
					"itemQtyUom": itemQtyUom,
					"itemAmount": itemAmount2Decimals,
					"itemAmountCurrency": itemAmountCurrency,
					"event": "ItemAdded",
					"eventId": eventId
				});

				if (!!addEcommerce) {

					if (!$window.pdpItems) {
						console.warn('pdpItems is not defined');
						return;
					}

					let item = $window.pdpItems.items.find(x => x.item_id == itemNo);
					if (!item) item = $window.pdpItems.items[0];

					item.quantity = Math.round(itemQty);
					item.sell_quantity = itemQty;

					let items = [item];

					$window.dataLayer.push({
						"ecommerceGA4": {
							"items": items
						},
						"event": "add_to_cart"
					});
				}
			};

			this.ItemViewedEvent = function (itemNo, addEcommerce) {
				if ($window.isProfessional === true) return;
				if (!$window.listItems) {
					console.warn('listItems is not defined');
					return;
				}

				let item = $window.listItems.items.find(x => x.item_id === itemNo);
				const items = !!item ? [item] : [];

				if (!!addEcommerce) {
					$window.dataLayer.push({
						"ecommerceGA4": {
							"items": items
						},
						"event": "select_item"
					});
				}
			};

			this.LocationSearchEvent = function (query, store, locations) {
				if ($window.isProfessional === true) return;
				$window.dataLayer.push({
					"store_id": store,
					"event": "store_locator",
					"location_search": query,
					"location_results": locations
				});
			}

			this.AddToFavoritesEvent = function (item) {
				if ($window.isProfessional === true) return;

				if (!$window.pdpItems) {
					console.warn('pdpItems is not defined');
					return;
				}

				$window.dataLayer.push({
					"ecommerceGA4": {
						"items": $window.pdpItems.items
					},
					"event": "add_to_favorites"
				});
			};

			this.CartOpenedEvent = function (cartId, addEcommerce) {
				if ($window.isProfessional === true) return;
				if (!!addEcommerce) {
					$window.dataLayer.push({
						"ecommerceGA4": {
							"cart_id": cartId
						},
						"event": "cart_open"
					});
				}
			};

			this.ErrorEvent = function (message) {
				if ($window.isProfessional === true) return;
				$window.dataLayer.push({
					"error_message": message,
					"event": "error_message"
				});
			};

			this.SiteFeatureEvent = function (name, detail) {
				if ($window.isProfessional === true) return;
				$window.dataLayer.push({
					"site_feature_name": name,
					"site_feature_detail": detail,
					"event": "site_feature"
				});
			};

			this.EmailSignupSuccess = function () {
				if ($window.isProfessional === true) return;
				$window.dataLayer.push({
					"event": "email_signup_success"
				});
			};

			this.ItemRemovedEvent = function (itemNo, addEcommerce) {
				if ($window.isProfessional === true) return;

				if (!$window.bagItems) {
					console.warn('bagItems is not defined');
					return;
				}

				let item = $window.bagItems.items.find(x => x.item_id === itemNo);
				const items = !!item ? [item] : [];

				if (!!addEcommerce && items.length > 0) {
					$window.dataLayer.push({
						"ecommerceGA4": {
							"items": items
						},
						"event": "remove_from_cart"
					});
				}
			};

			this.ViewItemEvent = function (itemNo, price, itemTitle, itemDescription, eventId) {
				if ($window.isProfessional === true) return;
				$window.dataLayer.push(_.pick({
					"itemNo": itemNo,
					"productSku": itemNo, //for backward compatibility
					"productName": itemTitle,
					"productDescription": itemDescription,
					"moqPrice": price,
					"event": "ViewItem",
					"eventId": eventId
				}, _.identity));
			};

			this.ViewItemCommerce = function (item, eventId) {
				if ($window.isProfessional === true) return;

				$window.pdpItems = {items: []};

				const _item = _.pick({
					price: item.price,
					color: item.color,
					item_id: item.code,
					quantity: item.qty,
					item_name: item.name,
					currency: item.currency,
					discount: item.discount,
					unit_of_measure: item.uom,
					sell_quantity: item.needed,
					item_category: item.category1,
					item_category2: item.category2,
					item_category3: item.category3,
					item_category4: item.category4,
					stock_flag: item.isInStock ? "in stock" : "not available",
					index: 0,
					item_list_id: 0,
					item_list_name: "Product List",
					item_brand: "Bedrosians Tile & Stone",
					affiliation: "Bedrosians Tile & Stone",
				}, _.identity);

				$window.pdpItems.items.push(_item);

				$window.dataLayer.push(_.pick({
					eventId,
					event: 'view_item',
					ecommerceGA4: {
						items: [_item]
					}
				}, _.identity));
			}

			this.ItemOpened = function (item, moqPrice) {
				if ($window.isProfessional === true) return;

				$window.dataLayer.push(_.pick({
					moqPrice,
					eta: item.eta,
					productUrl: item.productUrl,
					productSku: item.productSku,
					productName: item.productName,
					availability: item.availability,
					productSeries: item.productSeries,
					productImageUrl: item.productImageUrl,
					productDescription: item.productDescription,
				}, _.identity))
			}

			this.AddPageSchema = function (schema) {
				const tag = angular.element('script[type="application/ld+json"]');
				tag.html(JSON.stringify(schema));
				console.log(tag);
				angular.element('head').append(tag);
			}
		}]);
})();
;
(function () {
	'use strict'
	
	window.bdApp.factory('$serviceInjector', [
		'$injector',
		'$rootScope',
		(injector, scope) => ({
			inject(services) {
				let keys = Object.keys(services);
				keys.map(key => injector.has(services[key]) && (scope[key] = injector.get(services[key])));
			}
		})
	])
})();
(function () {
	'use strict';

	function UomConversionService(appUtils, uomConverter) {

		function adjustSellQtyToSolidBaseUnitQty(sellQty, sellingUom) {
			if (sellingUom.IsFractional) {
				var baseQty = uomConverter.toBaseUom(sellQty, sellingUom); // whole base qty
				var adjustedSellQty = 0;
				// workaround refs http://gitlab.bedrosians.com/Bedrosians/oep/issues/4827#
				// due to system store/calculate 4 digits but a user see/enter only 2 digits
				var sellQtyPrecision4 = uomConverter.fromBaseUom(baseQty - 1, sellingUom, 4);
				if (appUtils.round(sellQtyPrecision4, 2) === appUtils.round(sellQty, 2)) {
					adjustedSellQty = sellQtyPrecision4;
				} else {
					adjustedSellQty = uomConverter.fromBaseUom(baseQty, sellingUom, 4);
				}

				return adjustedSellQty;
			} else {
				return Math.floor(appUtils.round(sellQty, 2)); // just round down to the nearest integer value
			}
		}

		function calculateTotalHandlingQty(sellQty, sellingUom, handlingUom) {
			if (sellQty === 0) {
				return 0;
			}
			return Math.ceil(uomConverter.toUom(sellQty, sellingUom, handlingUom));
		}

		function calculateSellingPerHandlingQty(sellingUom, handlingUom) {
			return uomConverter.toUom(1, handlingUom, sellingUom);
		}

		return {
			calculateTotalHandlingQty: calculateTotalHandlingQty,
			calculateSellingPerHandlingQty: calculateSellingPerHandlingQty,
			adjustSellQtyToSolidBaseUnitQty: adjustSellQtyToSolidBaseUnitQty,
		};
	}

	angular.module('app').service('UomConversionService', ['appUtils', 'uomConverter', UomConversionService]);
})();
;
(function () {
	'use strict';
	window.bdApp.service('$frontendAccount', function ($client, appSettings) {
		return {
			invoices: (params) => $client.frontGet(appSettings.getSecureUrl(`account/invoices`, true), params),
		}
	});
})()
;
(function() {
	'use strict';
	
	window.bdApp.service('$banner', function ($client) {
		return {
			list: (data) => $client.api(`banner/list`, 'POST', data),
		}
	});
})()
;
(function () {
	'use strict';
	
	window.bdApp.service('$customer', function ($client) {
		return {
			getbalance: () => $client.api(`customer/getbalance`, 'GET'),
		}
	});
})()
;
(function () {
	'use strict';
	
	window.bdApp.service('$gallery', function ($client) {
		return {
			detail: (id, relatedPageSize = 0, relatedPageIndex = 1) => $client.api(`gallery/detail/${id}/${relatedPageSize}/${relatedPageIndex}`, 'GET'),
			refinements: () => $client.api(`gallery/refinements`, 'GET'),
			list: (data) => $client.api(`gallery/list`, 'POST', data),
		}
	});
	
	window.bdApp.service('$frontendGallery', function ($client, appSettings) {
		return {
			list: (request) => $client.frontend(appSettings.getUrl(`gallery/list?${request}`, true), 'GET', request, {'x-camelcase': 'true'}),
			detail: (id) => $client.frontend(appSettings.getSecureUrl(`gallery/detail/${id}`, true), 'GET', null, {'x-camelcase': 'true'}),
			refinements: () => $client.frontend(appSettings.getUrl("gallery/refinements", true), 'GET', null, {'x-camelcase': 'true'}),
		}
	});
})()
;
(function () {
	'use strict';
	
	window.bdApp.service('$client', function ($q, $http, $cookies, $webApiBaseUrl) {
		const http = (options) => {
			options.headers = {
				...options.headers,
				Accept: 'application/json',
			};
			
			let token = $cookies.get('WebApiTokenV1');
			if (token) options.headers.Authorization = `Bearer ${token}`;
			
			let deferred = $q.defer();
			
			$http(options).then(result => {
				if (result.data instanceof Array) deferred.resolve({value: result.data, __meta__: result})
				else deferred.resolve({...result.data, __meta__: result})
			}).catch(result => deferred.reject({__meta__: result}));
			
			return deferred.promise;
		}
		
		return {
			frontGet: (url, params, headers) => http({url, params, headers, method: 'GET'}),
			frontend: (url, method, data, headers) => http({url, data, method, headers}),
			api: (url, method, data, headers) => http({
				data, method, url: $webApiBaseUrl + url,
				headers: {...headers, StoreFrontPublicKey: window.StoreFrontPublicKey}
			}),
		}
	});
	
	window.bdApp.service('$api', function ($banner, $gallery, $customer, $webproduct, $storefront) {
		return {
			$banner,
			$gallery,
			$customer,
			$webproduct,
			$storefront,
		}
	});
	
	window.bdApp.service('$frontend', function ($product, $shoppingbag, $frontendAccount, $frontendGallery) {
		return {
			$product,
			$shoppingbag,
			$frontendAccount,
			$frontendGallery,
		}
	});
})();
(function() {
	'use strict';
	
	window.bdApp.service('$shoppingbag', function($client, appSettings) {
		return {
			addToBag: (data) => $client.frontend(appSettings.getSecureUrl(`shoppingbag/jsonaddtobag/`, true), 'POST', data),
		}
	});
})()
;
(function () {
	'use strict';

	window.bdApp.service('$storefront', function ($client) {
		return {
			getstateprovinces: (countryCode) => $client.api(`/storefront/getstateprovinces?countryCode=${countryCode}`, 'GET'),
		}
	});
})()
;
(function () {
	'use strict';

	angular.module('app').service('$apiTokenService', function ($q, $http, $cookies) {
		let loading = false;

		const handlers = [];

		// TODO get from config
		const cookieConfig = {path: '/'};
		const WebApiTokenCookie = 'WebApiTokenV1';
		const RefreshTokenRequest = 'RefreshTokenRequest';
		const WebApiRefreshTokenCookie = 'WebApiRefreshTokenV1';

		const decodeToken = (token) => {
			let base64Url = token.split('.')[1];
			let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
			let jsonPayload = decodeURIComponent(window.atob(base64).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));
			return JSON.parse(jsonPayload);
		}

		const tokenIsValid = (token, now) => {
			let payload = decodeToken(token);
			return payload.exp - 60 * 2 > now;
		}

		const tokenExpired = (token, now) => {
			let payload = decodeToken(token);
			return payload.exp < now;
		}

		const getToken = () => {
			if (loading) return new Promise(rs => handlers.push(rs));

			let now = Math.floor(Date.now() / 1000);
			let authToken = $cookies.get(WebApiTokenCookie, cookieConfig);
			let refreshToken = $cookies.get(WebApiRefreshTokenCookie, cookieConfig);

			if (!authToken || !refreshToken) return Promise.resolve(null);

			if (authToken && tokenIsValid(authToken, now)) return Promise.resolve(authToken);

			loading = true;

			if (authToken && tokenExpired(authToken, now)) {
				$cookies.remove(WebApiTokenCookie, cookieConfig);
				$cookies.remove(WebApiRefreshTokenCookie, cookieConfig);
			}

			return $http.post(window.WebApiBaseUrl + 'account/refreshtokens', {refreshToken: refreshToken}).then((response) => {
				$cookies.put(WebApiRefreshTokenCookie, response.data.refreshToken, cookieConfig);
				$cookies.put(WebApiTokenCookie, response.data.authToken, cookieConfig);
				loading = false;
				return authToken;
			}, (error) => window.location.reload())
				.then((token) => handlers.map(rs => rs(token)));
		}

		return {
			getToken
		}
	});
})()
;
(function () {
	'use strict';

	window.bdApp.service('$webproduct', function ($injector, $filter, $client, branchLocatorService) {
		return {
			availability: (itemNo, unit, productAvailabilityRequest) => $client.api(`webproducts/availability/${itemNo}/${unit}`, 'POST', {productAvailabilityRequest}),
			detail: (itemNo, styleName, data) => $client.api(`webproducts/detail/${itemNo}/${styleName}`, 'POST', data),
			getrelateditems: (relationType, itemNoList = [], useCache = false) => {
				let customerId = $injector.has('$customerId') ? $injector.get('$customerId') : null;
				let state = branchLocatorService.GetShippingStateName();
				let country = branchLocatorService.GetShippingCountryName();
				let hash = $filter('md5')(JSON.stringify(itemNoList) + relationType + customerId);
				let url = 'webproducts/getrelateditems' + (useCache ? `?cacheKey=${hash}-${country}-${state}&cacheDurationInSeconds=43200` : '');
				return $client.api(url, 'POST', {
					relationType,
					itemNoList,
					maxItems: 10,
					ShippingStateCode: state,
					ShippingCountryCode: country,
				})
			},
			list: (data, collection) => {
				let state = branchLocatorService.GetShippingStateName();
				let country = branchLocatorService.GetShippingCountryName();
				let cacheKey = `${collection ? collection + '-' : ''}${country}-${state}-${$filter('md5')(JSON.stringify(data))}`;
				return $client.api(`webproducts/list?cacheKey=${cacheKey}&cacheDurationInSeconds=3600`, 'POST', data);
			},
		}
	});

	window.bdApp.service('$product', function ($client, appSettings) {
		return {
			getAssociatedCollectionImages: (collection, limit) => $client.frontend(appSettings.getSecureUrl(`ProductAssociator/GetCollectionImages/?collection=${collection}&limit=${limit}`, true), 'GET'),
			getAssociatedProductImages: (itemNo, limit) => $client.frontend(appSettings.getSecureUrl(`ProductAssociator/GetAssociatedImagesByProduct/?productNo=${itemNo}&limit=${limit}}`, true), 'GET'),
			availability: (itemNo, unit) => $client.frontend(appSettings.getSecureUrl(`product/availability?itemNo=${itemNo}&unit=${unit}`, true), 'GET'),
			getTearsheet: (series) => $client.frontend(appSettings.getUrl("product/tearsheet", true), 'POST', {productSeries: series}),
			detail: (itemNo) => $client.frontend(appSettings.getSecureUrl(`product/detail?itemNo=${itemNo}`, true), 'GET'),
		}
	});
})()
;
(function () {
	'use strict';
	
	window.bdApp.service("$galleryListRequestBuilder", function () {
		return function () {
			this.request = null;
			
			this.addFacet = (key, values) => {
				this.request.facets.push({key, values})
				return this;
			};
			
			this.setPageIndex = (index) => {
				this.request.pageIndex = index;
				return this;
			}
			
			this.reset = () => {
				this.request = {
					sort: null,
					facets: [],
					pageSize: 60,
					pageIndex: 1,
				};
				return this;
			};
			
			this.reset();
			
			return this;
		}
	});
})();
(function () {
	'use strict';
	
	window.bdApp.service('$requestBuilders', function ($galleryListRequestBuilder, $webproductListRequestBuilder) {
		return {
			$galleryListRequestBuilder,
			$webproductListRequestBuilder,
		}
	});
})();
(function () {
	'use strict';

	window.bdApp.service("$webproductListRequestBuilder", function () {
		return function () {
			this.sort = 'relevance';
			this.disableFacets = false;
			this.facets = [];
			this.categories = [];

			this.parameters = {};
			this.baseShippingCountryCode = 'US';

			this.addFacet = (key, values) => {
				let _values = Array.isArray(values) ? values : [values];
				this.facets.push({key, values: _values});
				return this;
			}

			this.parseQuery = (query) => {
				const _query = new URLSearchParams(query);
				const keys = _query.keys();
				for (let _key of keys) {
					if (!_key.includes('f_')) continue;
					let key = _key.replace(/f_/g, '');
					let values = _query.get(_key).split(',');
					this.addFacet(key, values);
				}
			}

			this.addCategory = (value) => {
				let categories = (Array.isArray(value)) ? value : value.includes('/') ? value.split('/').filter(s => !!s) : [value]
				this.categories.push(...categories);
				return this;
			}

			this.setDisableFacets = (value) => {
				this.disableFacets = value;
				return this;
			}

			this.setSort = (value) => {
				this.sort = value.replace(/-/g, '_');
				return this;
			}

			this.addParameter = (key, value) => {
				this.parameters[key] = value;
				return this;
			}

			this.make = () => {
				if (!this.parameters['pageIndex'])
					this.parameters['pageIndex'] = 99;

				let parameters = {
					...this.parameters,
					Sort: this.sort,
					Facets: this.facets,
				};

				let navInfo = {
					Parameters: parameters,
					Categories: this.categories,
				};

				let request = {
					NavInfo: navInfo,
					BaseShippingCountryCode: this.baseShippingCountryCode,
					disableFacets: this.disableFacets
				};

				return request;
			}

			return this;
		}
	});
})()
;
(function () {
	'use strict'

	const bdAccordion = [
		'$parse',
		function ($parse) {
			return {
				scope: false,
				link(scope, elem, attrs) {
					let key = ($parse(attrs.bdAccordion))(scope);
					let preopen = ($parse(attrs.bdAccordionPreopen))(scope);
					elem.removeAttr('bd-accordion');
					const toggle = () => {
						let container = angular.element(`[data-key="${key}"]`);
						container.slideToggle('slow');
						elem.toggleClass('bd-filter-title-open');
						// elem.toggleClass('bd-filter-open');
					}
					scope.$on('$destroy', () => elem.off('click', toggle));
					elem.on('click', toggle);
					preopen && toggle();
				}
			}
		}
	];

	window.bdApp.directive('bdAccordion', bdAccordion);
})()
;
(function() {
	'use strict';
	
	let template = `
		<div class="bd-blog-slider bd-blog-slider-{{variant}}">
			<bd-slider plugins="['classNames','wheelGestures']" class="bd-blog-slider-container"><ng-transclude-replace></ng-transclude-replace></bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdBlogSlider', () => ({
		template,
		replace: true,
		transclude: true,
		scope: {variant: "@"}
	}))
	
	let templateItemA = `
		<ng-content-replace>
			<bd-slide>
				<bd-stack class="bd-blog-slider-item bd-blog-slider-item-a" flex-direction="column">
					<img class="bd-blog-slider-item-image lazyload" data-src="{{image}}" />
					<bd-stack class="bd-blog-slider-item-content" flex-direction="column">
						<ng-transclude-replace slot="title"></ng-transclude-replace>
						<ng-transclude-replace slot="subtitle"></ng-transclude-replace>
						<ng-transclude-replace slot="date"></ng-transclude-replace>
						<bd-stack class="bd-blog-slider-item-content-description" flex-direction="row" align-items="center" justify-content="center">
							<ng-transclude-replace slot="description"></ng-transclude-replace>
							<a class="bd-blog-slider-item-link" ng-href="{{href}}">
								<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50" fill="none">
								  <circle cx="25" cy="25" r="24.5" transform="matrix(1 -8.74228e-08 -8.74228e-08 -1 0 50)" stroke="#9E9E9E"/>
								  <path d="M22 33L31 25L22 17" stroke="#9E9E9E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
								</svg>
							</a>
						</bd-stack>
					</bd-stack>
				</bd-stack>
			</bd-slide>
		</ng-content-replace>
	`;
	
	let templateItemB = `
		<ng-content-replace>
			<bd-slide>
				<bd-stack class="bd-blog-slider-item bd-blog-slider-item-b" flex-direction="row">
					<img class="bd-blog-slider-item-image" ng-src="{{image}}" />
					<bd-stack class="bd-blog-slider-item-content" flex-direction="column">
						<ng-transclude-replace slot="title"></ng-transclude-replace>
						<ng-transclude-replace slot="subtitle"></ng-transclude-replace>
						<ng-transclude-replace slot="date"></ng-transclude-replace>
						<ng-transclude-replace slot="description"></ng-transclude-replace>
					</bd-stack>
				</bd-stack>
			</bd-slide>
		</ng-content-replace>
	`;
	
	let itemTemplates = [{key: 'a', template: templateItemA}, {key: 'b', template: templateItemB}];
	
	window.bdApp.directive('bdBlogSliderItem', () => ({
		replace: true,
		template: ($elem) => {
			let variant = $elem.parent().attr('variant');
			return itemTemplates.find(x => x.key === variant).template;
		},
		transclude: {
			date: "?bdBlogItemDate",
			title: "?bdBlogItemTitle",
			subtitle: "?bdBlogItemSubtitle",
			description: "?bdBlogItemDescription",
		},
		scope: {
			image: "@",
			href: "@",
		}
	}))
	
	window.bdApp.directive('bdBlogItemDate', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-blog-slider-item-date"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}))
	window.bdApp.directive('bdBlogItemTitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-blog-slider-item-title"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}))
	window.bdApp.directive('bdBlogItemSubtitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-blog-slider-item-subtitle"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}))
	window.bdApp.directive('bdBlogItemDescription', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-blog-slider-item-description"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}))
})();
(function () {
	'use strict';
	
	let templateUrl = `
		<a ng-target="{{target}}" ng-href="{{href}}" class="bd-button bd-button-{{variant}}">
			<ng-transclude-replace></ng-transclude-replace>
		</a>
	`;
	
	let templateButton = `
		<button class="bd-button bd-button-{{variant}}">
			<ng-transclude-replace></ng-transclude-replace>
		</button>
	`;
	
	window.bdApp.directive('bdButton', () => {
		return {
			replace: true,
			transclude: true,
			scope: { href: "@", target: "@", variant: "@", },
			template: (element, attributes) => (attributes.href) ? templateUrl : templateButton,
		}
	})
})();
(function() {
	'use strict';
	
	let template = `
		<div class="bd-category-banner-v2">
			<div class="bd-category-banner-v2-content" style="height:{{height}}">
				<div class="bd-category-banner-v2-intro">
					<ng-transclude-replace slot="title"></ng-transclude-replace>
					<ng-transclude-replace slot="description"></ng-transclude-replace>
				</div>
				<img ng-src="{{image}}" class="bd-category-banner-v2-image" />
			</div>
		</div>
	`;
	
	window.bdApp.directive('bdCategoryBanner', () => ({
		template,
		replace: true,
		scope: {image: "@", height: "@"},
		transclude: {
			title: "bdCategoryBannerTitle",
			description: "bdCategoryBannerDescription",
		},
	}));
	
	window.bdApp.directive('bdCategoryBannerTitle', () => ({
		replace: true,
		transclude: true,
		template: `<p class="bd-category-banner-v2-title"><ng-transclude-replace></ng-transclude-replace></p>`
	}))
	
	window.bdApp.directive('bdCategoryBannerDescription', () => ({
		replace: true,
		transclude: true,
		template: `<p class="bd-category-banner-v2-description"><ng-transclude-replace></ng-transclude-replace></p>`
	}))
})();
(function () {
	'use strict';

	let template = `
		<div class="bd-new-arrivals">
			<h1 class="bd-new-arrivals-title">{{title}}</h1>
			<ng-transclude-replace></ng-transclude-replace>
			<bd-preloader ng-if="loading" template="preloader"></bd-preloader>
			<div ng-if="!loading && items.length <= 0">Nothing found yet</div>
			<div class="bd-new-arrivals-section" ng-if="!loading && items.length > 0" ng-repeat="item in items">
				<h2 class="bd-new-arrivals-collection-title">{{item.collection.title}}</h2>
				<p class="bd-new-arrivals-collection-description" ng-if="item.collection.description">{{item.collection.description}}</p>
				<bd-slider-up class="bd-new-arrivals-slider" options="sliderOptions" plugins="sliderPlugins">
					<div ng-if="item.collection.image" class="bd-new-arrivals-image-slide">
						<bd-image-detail width="460" height="360" image="item.collection.image"></bd-image-detail>
					</div>
					<div class="bd-new-arrivals-item-card product-card" ng-repeat="product in item.products">
						<div class="product-card-image-container skeleton">
							<a href="{{product.__href}}" target="_blank">
								<bd-image src="{{'/cdn-bedrosian/assets/products/hiresimages/' + product.imageName}}" width="250" height="250"></bd-image>
							</a>
						</div>
						<h3 class="plp-item-title"><a href="{{product.__href}}" target="_blank">{{product.name}}</a></h3>
						<div class="plp-item-info">
							<p class="plp-item-info-price">{{product.priceToDisplay.currentPrice | currency}} / {{product.sellingUom.name}}</p>
							<p class="plp-item-info-code">{{product.productCode}}</p>
							<button ng-if="product.sampleItemNo" class="plp-item-info-actions bd-button bd-button-border" ng-click="addSampleToBag(product.sampleItemNo)">Order Sample</button>
							<a href="{{product.__href}}" ng-if="!product.sampleItemNo" class="plp-item-info-actions bd-button bd-button-border">View Item</a>
						</div>
					</div>
				</bd-slider-up>
				<bd-button class="catalog-cta" style="margin-top: 20px" href="{{item.href}}" variant="dark">Shop {{item.collection.title}}</bd-button>
			</div>
		</div>
	`;

	let preloaderTemplate = `
		<div class="bd-new-arrivals-section" ng-repeat="item in [1,2,3,4,5,6]">
			<p style="width:200px"></p>
			<p style="width:250px"></p>
			<div style="display: grid; grid-auto-flow: column; grid-auto-columns: min-content">
				<div class="bd-new-arrivals-item-card product-card" ng-repeat="item in [1,2,3,4,5,6]">
					<div class="product-card-image-container skeletron-image"></div>
					<p style="width:100%;margin-top:10px;"></p>
					<p style="width:150px;min-height:15px"></p>
					<p style="width:50px;min-height:10px"></p>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdCategorySlider', ($api, $parse, $requestBuilders, $addSampleDialog, appSettings) => {
		return {
			template,
			scope: true,
			replace: true,
			transclude: true,
			compile: (element, attr) => {
				return (scope) => {
					scope.title = attr.title ? attr.title : undefined;

					scope.preloader = preloaderTemplate;

					scope.sliderOptions = {
						align: 'end',
						skipSnaps: true,
					};

					scope.sliderPlugins = [EmblaCarouselWheelGestures()];

					let category = ($parse(attr.category))(scope) || ($parse(attr.$attr.category))(attr);

					let requestBuilder = $requestBuilders.$webproductListRequestBuilder();

					let sort = attr.sort ? attr.sort : undefined;
					let request = requestBuilder.addCategory(category)
						.setSort(sort);

					if (scope.collections.length > 0) {
						request.addFacet('ProductSeries', scope.collections.map(x => x.name));
					}

					$api.$webproduct.list(request.make()).then((res) => {
						if (!res.value) return;
						scope.items = Object.entries(
							scope.collections.reduce((group, item) => {
								group[item.name] = {
									products: res.value.products.filter(x => x.productSeries.toLowerCase() === item.name.toLowerCase()).map(item => (item.__href = appSettings.getSecureUrl(`product/detail${item.urlFriendlyStyleName ? '/' + item.urlFriendlyStyleName : ''}/?itemNo=${item.productCode}`, true), item)),
									href: appSettings.getSecureUrl(`product/list/?f_ProductSeries=${item.name}`, true),
									collection: item,
								}
								return group;
							}, {})
						).map(([key, value]) => value);

						scope.items = scope.items.sort((a, b) => {
							let aIndex = scope.collections.indexOf(a.collection);
							let bIndex = scope.collections.indexOf(b.collection);
							if (aIndex < 0) aIndex = scope.items.length + 1;
							if (bIndex < 0) bIndex = scope.items.length + 1;
							return (aIndex - bIndex);
						});

						scope.loading = false;
					});

					delete attr['title'];
				}
			},
			controller: function ($scope) {
				$scope.loading = true;
				$scope.products = [];
				$scope.collections = [];

				$scope.addSampleToBag = (sampleNo) => $addSampleDialog.showDialog(sampleNo);

				this.addCollection = (collection) => {
					$scope.collections.push(collection);
				}

				this.addProducts = (products) => {
					$scope.products.push(...products);
				}
			},
		}
	});

	window.bdApp.directive('bdCategorySliderItem', () => {
		return {
			replace: true,
			scope: {
				name: "@",
				image: "@",
				products: "=",
				collection: "@",
				description: "@",
			},
			require: "^^bdCategorySlider",
			link: ($scope, $element, $attr, $ctrl) => {
				if ($scope.products) $ctrl.addProducts($scope.prodcuts);
				$ctrl.addCollection({
					title: $scope.name,
					image: $scope.image,
					name: $scope.collection,
					description: $scope.description,
				});
				$element.remove();
			}
		}
	});
})()
;
(function() {
	'use strict';
	
	let template = `
		<div class="bd-citizens-pay-banner">
			<div class="bd-citizens-pay-banner-column">
				<div class="bd-citizens-pay-banner-row">
					<img class="bd-citizens-pay-banner-logo" src="//res.cloudinary.com/bedrosians/image/upload/f_auto,w_1024/v1/assets/2022/Banners/1%20-%20Homepage/4%20-%20April/CitizensPay-White.png" alt=""/>
					<span class="bd-citizens-pay-banner-title">Tile Now, Pay Later.</span>
				</div>
				<span class="bd-citizens-pay-banner-subtitle">When you make a purchase at Bedrosians using Citizens Pay® at checkout, you’ll enjoy zero down payments and interest as low as 0% APR.*</span>
				<hr />
				<span class="bd-citizens-pay-banner-addon">*Promotional APR: Available on qualifying purchases of select products charged to a Citizens Pay Line of Credit account. Minimum purchase: $799. 0% APR – 1.99% APR from the date an eligible purchase is posted to your account until paid in full. Promotional offers may vary by purchase amount. Limited time offer. Other transactions affect overall minimum payment amount. Regular account terms apply to non-promo purchases. Standard Purchase APR is 29.99% for non-promotional purchases. Account must be in good standing. Subject to credit approval. Go to <a href="https://www.citizensbank.com/disclosures/GenericAPR-CT-CitizensPay.aspx" target="_blank">https://www.citizensbank.com/disclosures/GenericAPR-CT-CitizensPay.aspx</a> for important information about Rates and Fees and the Citizens Pay Line of Credit Agreement. Citizens Pay Line of Credit Account offered by Citizens Bank, N.A.</span>
			</div>
		</div>
	`;
	
	window.bdApp.directive('bdCitizensPayBanner', () => ({
		template,
		replace: true,
	}))
})();
(function(){
	'use strict';
	
	let template = `
		<a ng-click="onClick()" style="cursor:pointer">
			<img alt="Citizens Pay logo" class="citizens-logo" src="https://res.cloudinary.com/bedrosians/image/upload/f_auto,c_fill,w_150/v1/assets/content/icons/42045ac4c5785e985e0d11720756cedd" />
		</a>
	`;
	
	window.bdApp.directive('bdCititzensPayButton', () => ({
		template,
		replace: true,
		controller: ($scope, $window) => {
			$scope.onClick = () => {
				$window.open('//bedrosians.citizensbank.com/?src=87&storeId=500', null, 'popup');
			}
		}
	}))
})()
;
(function () {
	"use strict";

	let collections = [
		{
			key: "Modni",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002559.pdf",
			gallery: ["modni-100001697-inst", "modni-100001704-inst", "modni-100001699-inst"],
			description: "Got a flair for the geometric? Modni is just your style. Stunning from any angle, the Modni Collection embraces the unexpected, with shapes and forms that create a refreshing take on symmetry. As one of our more unique collections of marble blend mosaics, Modni blurs the lines between extravagance and refinement."
		},
		{
			key: "Atrium",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002556.pdf",
			gallery: ["atrium-100001723-inst", "atrium-100001720-inst-1", "atrium-100001722-inst"],
			description: "Though its name is synonymous with grand entrances, Atrium is designed to luxuriate any room or surface, be it in a residential or commercial space. Crafted in four tonal combinations, the collection offers a range of subtleness and drama to reflect your personal style."
		},
		{
			key: "Matisse",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002561.pdf",
			description: "Elegance isn’t just a style. It’s an artform. And nothing embodies it quite like the Matisse Collection, a series of stunning marble blend mosaics. A study in contrasts and abstract patterns, the Matisse Collection ignites a creative spark while maintaining a sense of structure."
		},
		{
			key: "Solis",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002557.pdf",
			gallery: ["solis-100001719-inst-hag-p1-4", "solis-100001717-inst", "solis-100001716-inst"],
			description: "The Solis Collection features four stone blend designs, each with their own level of energy, perfectly suited for a statement wall, floor or shower. Choose tones with less contrast for a lighter, airier feel, or up the contrast to highlight Solis’s patterns and visual intrigue."
		},
		{
			key: "Celeste",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002558.pdf",
			gallery: ["celeste-100001715-inst", "celeste-100001713-inst-1", "celeste-100001712-inst-2"],
			description: "No need for a telescope to bring you closer to the stars. The Celeste Collection, inspired by the starry sky above, will elevate any space in your home—kitchen, bathroom, flooring, statement walls and more. Celeste’s dreamy swirls of color and texture create shapely motifs that effortlessly blend into one another, delivering a vibe that’s nothing short of heavenly."
		},
		{
			key: "Monet",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/100002560.pdf",
			gallery: ["monet-100001380-inst", "monet-100001385-inst", "monet-100001410-inst"],
			description: "The Solis Collection features four stone blend designs, each with their own level of energy, perfectly suited for a statement wall, floor or shower. Choose tones with less contrast for a lighter, airier feel, or up the contrast to highlight Solis’s patterns and visual intrigue."
		},
		{
			key: "Ferrara",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/MKTTERDECFER.pdf",
			gallery: ["ferrara-001-ferrara-nero", "ferrara-decferbiachemoh-inst-chi-p1-1", "ferrara-decferner36h-inst-mhi-p1-1"],
			description: "Add a touch of shine with the Ferrara Collection. This collection of marble stone tile features 3” x 6” decorative and field tiles, 1” x 1” mosaics, and multi-size chevron mosaics. Available in 3 neutral brass accented shades, it is perfect for residential and commercial wall applications. Mix and match for a variety of unique design options."
		},
		{
			key: "Blomma",
			tearsheet: "http://cdn.bedrosians.com/assets/products/pdfs/MKTTERDECBLO.pdf",
			description: "Add depth, dimension, and personality to any space with the Blomma Collection. Available in a 12”x12” marble mosaic in 3 monochrome hues, this collection of decorative natural stone tile features a playful floral pattern. The perfect pick for indoor/outdoor residential and commercial use and for elevating the look of walls, shower walls, countertops, and indoor flooring."
		},
	];

	let template = `
		<div class="bd-collection-display">
			<bd-landing-section ng-repeat="item in items">
				<bd-display on-hide="(min-width:1024px)">
					<bd-stack gap="40px" flex-direction="column">
						<bd-typography class="bd-landing-simple-title">{{item.key}}</bd-typography>
						<bd-collection-gallery collection="{{item.key}}" gallery="item.gallery"></bd-collection-gallery>
						<bd-typography class="bd-landing-simple-text">{{item.description}}</bd-typography>
						
						<bd-display on-hide="(min-width:768px)">
							<bd-stack flex-direction="column">
								<bd-typography class="bd-landing-simple-subtitle">Avaliable in:</bd-typography>
								<bd-typography class="bd-landing-simple-subtext">{{item.colorsCount}} Colors | {{item.patternCount}} Pattern</bd-typography>
							</bd-stack>
						</bd-display>
						
						<bd-display on-visible="(min-width:768px)">
							<bd-stack flex-direction="row" justify-content="space-between">
								<bd-stack flex-direction="column">
									<bd-typography class="bd-landing-simple-subtitle">Avaliable in:</bd-typography>
									<bd-typography class="bd-landing-simple-subtext">{{item.colorsCount}} Colors | {{item.patternCount}} Pattern</bd-typography>
								</bd-stack>
								<bd-button target="_blank" variant="link" href="{{item.tearsheet}}">Download Tearsheet</bd-button>
							</bd-stack>
						</bd-display>
						
						<bd-slider plugins="['classNames','wheelGestures']" class="bd-color-palette" ng-if="item.switcher">
							<bd-slide ng-repeat="shape in item.shapes">
								<bd-stack flex-direction="column">
									<img class="bd-color-palette-item" ng-repeat="color in shape.items" data-color="{{color.seriesColor}}"
										src="//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{color.imageName}}" />
								</bd-stack>
							</bd-slide>
						</bd-slider>
						
						<bd-slider plugins="['classNames','wheelGestures']" class="bd-color-palette" ng-if="!item.switcher">
							<bd-slide ng-repeat="color in item.colors">
								<bd-stack flex-direction="column">
									<img class="bd-color-palette-item" ng-repeat="shape in color.items" data-color="{{shape.seriesColor}}"
										src="//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{shape.imageName}}" />
								</bd-stack>
							</bd-slide>
						</bd-slider>
						
						<bd-display on-hide="(min-width:768px)">
							<bd-stack flex-direction="column" align-items="center" justify-content="center">
								<bd-button href="{{item.href}}" variant="dark">Shop {{item.key}} Collection</bd-button>
								<bd-button target="_blank" variant="link" href="{{item.tearsheet}}">Download Tearsheet</bd-button>
							</bd-stack>
						</bd-display>
						
						<bd-display on-visible="(min-width:768px)">
							<bd-stack flex-direction="column" align-items="center" justify-content="center">
								<bd-button href="{{item.href}}" variant="dark">Shop {{item.key}} Collection</bd-button>
							</bd-stack>
						</bd-display>
					</bd-stack>
				</bd-display>
				<bd-display on-visible="(min-width:1024px)">
					<bd-stack flex-direction="row">
						<bd-stack class="left-side">
							<bd-collection-gallery collection="{{item.key}}" gallery="item.gallery"></bd-collection-gallery>
						</bd-stack>
						
						<bd-stack class="right-side" flex-direction="column" justify-content="space-between">
							<bd-stack flex-direction="column">
								<bd-typography class="bd-landing-simple-title">{{item.key}}</bd-typography>
								<bd-stack flex-direction="row" class="some-class-1">
									<bd-typography class="bd-landing-simple-text">{{item.description}}</bd-typography>
									<bd-stack flex-direction="column" align-items="center" justify-content="center">
										<bd-button href="{{item.href}}" variant="dark">Shop {{item.key}} Collection</bd-button>
										<bd-button target="_blank" variant="link" href="{{item.tearsheet}}">Download Tearsheet</bd-button>
									</bd-stack>
								</bd-stack>
							</bd-stack>
							
							<bd-stack flex-direction="column">
								<bd-stack flex-direction="column" class="some-class-2">
									<bd-typography class="bd-landing-simple-subtitle">Avaliable in:</bd-typography>
									<bd-typography class="bd-landing-simple-subtext">{{item.colorsCount}} Colors | {{item.patternCount}} Pattern</bd-typography>
								</bd-stack>
									
								<bd-slider plugins="['classNames','wheelGestures']" class="bd-color-palette" ng-if="item.switcher">
									<bd-slide ng-repeat="shape in item.shapes">
										<bd-stack flex-direction="column">
											<img class="bd-color-palette-item" ng-repeat="color in shape.items" data-color="{{color.seriesColor}}"
												src="//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{color.imageName}}" />
										</bd-stack>
									</bd-slide>
								</bd-slider>
								
								<bd-slider plugins="['classNames','wheelGestures']" class="bd-color-palette" ng-if="!item.switcher">
									<bd-slide ng-repeat="color in item.colors">
										<bd-stack flex-direction="column">
											<img class="bd-color-palette-item" ng-repeat="shape in color.items" data-color="{{shape.seriesColor}}"
												src="//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{shape.imageName}}" />
										</bd-stack>
									</bd-slide>
								</bd-slider>
							</bd-stack>
						</bd-stack>
					</bd-stack>
				</bd-display>
			</bd-landing-section>
		</div>
	`;

	window.bdApp.directive("bdCollectionDisplay", ($api, $requestBuilders, appSettings) => {
		return {
			template,
			replace: true,
			transclude: true,
			scope: {
				materialType: "@",
				materialCategory: "@",
			},
			link: ($scope) => {
				let requestBuilder = $requestBuilders.$webproductListRequestBuilder()
					.addFacet('MaterialCategory', $scope.materialCategory)
					.addFacet('MaterialType', $scope.materialType);

				$api.$webproduct.list(requestBuilder.make()).then((res) => {
					$scope.items = collections.map(i => {
						i.items = res.data.value.products.filter(x => x.productSeries === i.key)
							.map(x => (x.seriesColor = x.seriesColor.replace(/[\W_]+/g, '_'), x))
							.sort((a, b) => a.seriesColor < b.seriesColor ? 1 : -1);

						i.shapes = i.items.reduce((res, item) => {
							let key = `${item.shape}-${item.size}`;
							if (res.hasOwnProperty(key)) res[key].items.push(item);
							else res[key] = {items: [item]};
							return res;
						}, {});

						i.colors = i.items.reduce((res, item) => {
							let key = `${item.seriesColor}`;
							if (res.hasOwnProperty(key)) res[key].items.push(item);
							else res[key] = {items: [item]};
							return res;
						}, {});

						i.patternCount = Object.entries(i.shapes).length;

						i.colorsCount = Object.entries(i.colors).length;

						i.switcher = i.patternCount > i.colorsCount;

						i.href = appSettings.getSecureUrl(`product/list/?f_ProductSeries=${i.key}`, true);

						return i;
					});
				});
			}
		}
	})
})();
(function () {
	'use strict';

	var template = `
		<div class="bd-toolbox">
			<bd-preloader ng-if="!imageSrc">
				<div class="skeletron-image" style="width:100%;height:100%"></div>
			</bd-preloader>
			<bd-responsive-image loading="loading" class="bd-gallery-slider-image" ng-if="imageSrc" image-src="{{imageSrc}}" alt="{{imageAlt}}"></bd-responsive-image>
			<div class="bd-toolbox-wrapper" ng-if="products.length > 0">
				<div class="bd-toolbox-detail" ng-class="detailClass">
					<div class="bd-toolbox-detail-wrapper">
						<a ng-repeat="product in products" class="bd-toolbox-content" ng-href="{{product.href}}">
							<bd-responsive-image width="70" height="70" class="bd-toolbox-thumbnail" image-src="{{product.src}}"></bd-responsive-image>
							<p class="bd-toolbox-title">{{product.title}}</p>
						</a>
					</div>
					<div class="bd-toolbox-button">Shop this look</div>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdCollectionGalleryDetail', ($http, $timeout, $cookies, appSettings) => {
		return {
			template,
			replace: true,
			scope: {
				image: "=?",
				loading: "@?",
				variant: "@?",
				imageId: "@?",
				position: "@?",
				imageSrc: "@?",
			},
			controller: ($api, $scope) => {
				$scope.products = [];
				$scope.detailClass = [];

				$scope.breakpoints = {
					'(min-width: 1200px)': 1720,
					'(min-width: 1024px)': 1200,
					'(min-width: 768px)': 1000,
					'(min-width: 0px)': 768,
				}

				if ($scope.variant) $scope.detailClass.push(`bd-toolbox-detail-${$scope.variant}`);
				if ($scope.position) $scope.detailClass.push(`bd-toolbox-detail-${$scope.position}`);

				$scope.imageId = $scope.imageId ? $scope.imageId : $scope.image && $scope.image.id;
				$scope.imageSrc = $scope.imageSrc ? $scope.imageSrc : $scope.image && $scope.image.src;
				$scope.imageAlt = $scope.imageAlt ? $scope.imageAlt : $scope.image && $scope.image.title;

				if (!$scope.imageSrc) $api.$gallery.detail($scope.imageId).then(res => {
					if (!res.value) return;
					$scope.imageSrc = res.value.relativeImages.images.find(img => img.id === $scope.imageId).src;
					$scope.products = res.value.products.map(i => (i.href = appSettings.getSecureUrl(`product/detail/?itemNo=${i.code}`, true), i));
					setTimeout(() => $scope.$digest(), 0);
				});
			}
		}
	})
})()
;
(function (){
	'use strict';
	
	var template = `
		<div class="bd-gallery-slider">
			<bd-slider plugins="['classNames','wheelGestures']" ng-if="images.length">
				<bd-slide ng-repeat="image in images track by $index">
					<bd-collection-gallery-detail image="image"></bd-collection-gallery-detail>
				</bd-slide>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdCollectionGallery', ($http, $timeout, $cookies) => {
		return {
			template,
			replace: true,
			scope: {
				collection: "@",
				gallery: "=?",
			},
			link: ($scope) => {
				$scope.images = [];
				
				let request = {
					"facets": [
						{
							"key": "Collection",
							"values": [$scope.collection]
						}
					],
					"pageIndex": 1,
					"pageSize": 99,
				};
				
				$http.post("https://frontapi.bedrosians.com/gallery/list", request, {headers:{"StoreFrontPublicKey":window.StoreFrontPublicKey}})
					.then(res => {
						let images = res.data.value.images;
						
						$scope.images = (
							($scope.gallery)
								? images.filter(x => $scope.gallery.includes(x.id))
								: images.splice(0, 3)
						).map(x => (x.src = x.src.replace('t_gallery_regular,f_auto', 'f_auto,c_fill,w_700'), x));
					});
			}
		}
	})
})();
(function () {
	let template = `
		<div class="bd-collection-variants">
			<bd-stack flex-direction="column">
				<bd-typography class="bd-collection-variants-title">Avaliable in:</bd-typography>
				<bd-typography class="bd-collection-variants-subtitle">
					<span ng-pluralize count="colorsCount" when="{'0':'No Colors','1':'{{colorsCount}} Color','other':'{{colorsCount}} Colors'}"></span>
				</bd-typography>
				<bd-slider plugins="['classNames','wheelGestures']" ng-if="!textOnly" class="bd-collection-variants-slider" slider="model.slider" items="colors">
					<bd-slide ng-repeat="color in colors">
						<bd-stack flex-direction="column">
							<img class="bd-collection-variants-item lazyload" ng-repeat="shape in color.items | limitTo: 4 | orderBy: '-size'" data-color="{{shape.seriesColor}}"
								data-src="//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{shape.imageName}}" />
						</bd-stack>
					</bd-slide>
				</bd-slider>
			</bd-stack>
		</div>
	`;
	
	window.bdApp.directive('bdCollectionVariant', () => ({
		template,
		replace: true,
		scope: {collection: "@", textOnly: "="},
		controller: ($api, $scope, $timeout, $requestBuilders) => {
			$scope.model = {
				slider: null
			}
			
			let requestBuilder = $requestBuilders.$webproductListRequestBuilder()
				.addFacet('ProductSeries', $scope.collection);
			
			$api.$webproduct.list(requestBuilder.make(), $scope.collection).then(res => {
				$scope.shapes = res.value.products.reduce((res, item) => {
					let key = ((item.shape) ? `${item.shape}-${item.size}` : `size-${item.size}`).replace(/[\W_]+/g, '_');
					if (res.hasOwnProperty(key)) res[key].items.push(item);
					else res[key] = {items: [item]};
					return res;
				}, {});
				
				$scope.colors = res.value.products.reduce((res, item) => {
					let key = `${item.seriesColor}`.replace(/[\W_]+/g, '_');
					if (res.hasOwnProperty(key)) res[key].items.push(item);
					else res[key] = {items: [item]};
					return res;
				}, {});
				
				$scope.patternCount = Object.entries($scope.shapes).length;
				$scope.colorsCount = Object.entries($scope.colors).length;
				
				$timeout(() => $scope.model.slider && $scope.model.slider.reInit(), 1000);
			});
		}
	}));
})();
;
(function () {
	'use strict';
	const template = `
		<script
			src="https://cdn.dashhudson.com/web/js/carousel-embed.js"
			type="text/javascript"
			data-lazy="true"
			data-name="likeshop-carousel"
			data-id="{{brandId}}"
			data-id-type="brand_id"
			data-call-to-action="learn_more"
			data-disable-product-new-tab="false"
		></script>
	`;
	window.bdApp.directive('bdDashHudson', ['$compile', ($compile) => ({
		link(scope, element, attributes) {
			scope.brandId = attributes.brandId;
			const tag = $compile(template)(scope);
			element.replaceWith(tag);
		}
	})]);
})()
;
(function () {
	'use strict';
	
	let template = `
		<div style="flex:1;width:100%;height:100%;" ng-show="display">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdDisplay', ($window, $timeout) => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
			scope: {
				onHide: "@",
				onVisible: "@",
			},
			link: (scope) => {
				scope.display = false;
				
				let update = () => {
					$timeout(() => scope.$apply(() => {
						scope.display = (!scope.onVisible && !scope.onHide)
							|| (scope.onHide && !window.matchMedia(scope.onHide).matches && !scope.onVisible)
							|| ((scope.onVisible && window.matchMedia(scope.onVisible).matches) && (!scope.onHide || !window.matchMedia(scope.onHide).matches));
					}))
				}
				
				angular.element($window).bind('resize', () => update());
				
				update();
			}
		}
	})
})();
(function () {
	'use strict';

	const contentTemplate = `
		<div class="bd-drawer-content">
			<div class="bd-drawer-header">
				<span>{{header}}</span>
				<button class="bd-drawer-close" aria-label="close" data-close="true">
			</div>
			<div class="bd-drawer-body">
				<slot></slot>
			</div>
		</div>
	`;

	window.bdApp.directive('bdDrawer', ['$compile', '$timeout', ($compile, $timeout) => ({
		transclude: true,
		scope: {to: '@?', open: "=?", left: "=?", close: "&?", header: "@?"},
		compile(elem, attrs, linker) {
			elem.remove();
			return (scope) => {
				scope.to ||= 'body';
				scope.open ||= false;
				scope.left ||= false;
				scope.opened ||= false;
				const html = angular.element('html');
				const body = angular.element('body');
				const placement = angular.element(scope.to);
				const drawer = angular.element('<div class="bd-drawer"></div>');
				const open = () => {
					const topScroll = window.scrollY;
					const scroll = window.innerWidth - document.body.clientWidth;

					html.css({
						height: '100%',
						overflow: 'hidden',
						paddingRight: scroll + 'px',
					});

					const content = $compile(contentTemplate)(scope);
					return linker(scope.$parent, (copy, slotScope) => {
						slotScope.$on('$destroy', () => content.remove());

						const slot = content.find('slot');
						if (slot) slot.replaceWith(copy);

						drawer.css({
							top: 0,
							left: '0',
							width: '100%',
							height: '100%',
							position: 'fixed',
							overflow: 'hidden',
							justifyContent: scope.left ? 'flex-start' : 'flex-end',
						});

						drawer.on('scroll', (event) => event.preventDefault());
						drawer.on('click', drawerClick);
						drawer.addClass('bd-drawer-in');
						drawer.empty().append(content);
						placement.append(drawer);
						scope.opened = true;
					});
				}
				const close = () => {
					html.css({
						height: '',
						overflow: '',
						paddingRight: '',
					});

					if (!scope.opened) return;

					drawer.addClass('bd-drawer-out');
					drawer.removeClass('bd-drawer-in');
					drawer.on('animationend', animationEnd);
				}

				const watcher = scope.$watch('open', (value) => value ? open() : close());

				const drawerClick = function (event) {
					scope.$apply(() => {
						if (event.target === this || event.target.dataset.close)
							scope.open = false;
					});
				}

				const animationEnd = () => {
					scope.$apply(() => {
						scope.opened = false;
						drawer.remove();
						if (scope.close) scope.close();
						drawer.removeClass('bd-drawer-out');
						drawer.off('animationend', animationEnd);
					});
				}

				const keyHandler = (event) => {
					scope.$apply(() => {
						if (event.key === 'Escape') scope.open = false;
					});
				}

				angular.element(document).on('keydown', keyHandler);

				scope.$on('$destroy', () => {
					angular.element(document).off('keydown', keyHandler);
					drawer.off('click', drawerClick);
					drawer.remove();
					watcher();
				});
			}
		}
	})])
})()
;
(function (){
	'use strict';
	
	var baseCloudinary = '//res.cloudinary.com/bedrosians/image/upload/f_auto/v1/';
	
	var template = `
		<div class="bd-gallery-slider">
			<bd-slider plugins="['classNames','wheelGestures']">
				<bd-slide ng-repeat="image in images track by $index">
					<img class="bd-gallery-slider-image" ng-src="{{image.url}}" alt="{{image.name}}" />
				</bd-slide>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdGallerySlider', ($http, $timeout, $cookies, appSettings) => {
		return {
			template,
			replace: true,
			scope: {
				tag: "@",
				
			},
			controller: ($scope) => {
				$http.get(`//res.cloudinary.com/bedrosians/image/sprite/${$scope.tag}.json`)
					.then(res => $scope.images = res.data.images.map(image => {
						image.url = `${baseCloudinary}${image.name}`;
						return image;
					}))
					.then(() => $timeout(() => $scope.$digest()));
			}
		}
	})
	
	
})();
(function(){
	'use strict';
	
	let templateModuleA = `
		<div class="bd-head-banner bd-head-banner-a">
			<div class="bd-head-banner-main-wrapper">
				<bd-slider plugins="['classNames','wheelGestures']">
					<ng-transclude-replace></ng-transclude-replace>
				</bd-slider>
			</div>
		</div>
	`;
	window.bdApp.directive('bdHeadBannerA', () => {
		return {
			scope: true,
			replace: true,
			transclude: true,
			template: templateModuleA,
		}
	});
	
	let templateModuleB = `
		<div class="bd-head-banner bd-head-banner-b">
			<bd-display on-hide="(min-width:768px)">
				<bd-stack flex-direction="column" class="bd-head-banner-wrapper">
					<bd-stack class="bd-head-banner-intro" flex-direction="column">
						<ng-transclude-replace slot="content"></ng-transclude-replace>
					</bd-stack>
					<bd-collection-gallery-detail loading="eager" position="right" image-id="{{image}}" image-src="{{imageSrc}}"></bd-collection-gallery-detail>
					<ng-transclude-replace slot="description"></ng-transclude-replace>
					<bd-stack flex-direction="row" justify-content="center" align-items="center" class="bd-head-banner-actions bd-head-banner-actions-row">
						<ng-transclude-replace slot="actions"></ng-transclude-replace>
					</bd-stack>
				</bd-stack>
			</bd-display>
			<bd-display on-visible="(min-width:768px)">
				<div class="bd-head-banner-wrapper">
					<bd-collection-gallery-detail loading="eager" variant="long" position="right" image-id="{{image}}" image-src="{{imageSrc}}"></bd-collection-gallery-detail>
					<div class="bd-head-banner-b-content">
						<div class="bd-head-banner-b-content-wrapper">
							<bd-stack class="bd-head-banner-intro" flex-direction="column">
								<ng-transclude-replace slot="content"></ng-transclude-replace>
								<ng-transclude-replace slot="description"></ng-transclude-replace>
								<bd-stack flex-direction="column" class="bd-head-banner-actions bd-head-banner-actions-column">
									<ng-transclude-replace slot="actions"></ng-transclude-replace>
								</bd-stack>
							</bd-stack>
						</div>
					</div>
				</div>
			</bd-display>
		</div>
	`;
	window.bdApp.directive('bdHeadBannerB', () => {
		return {
			replace: true,
			scope: {image:"@", imageSrc: "@"},
			template: templateModuleB,
			transclude: {
				actions: "?bdHeadBannerActions",
				content: "?bdHeadBannerContent",
				disclaimer: "?bdHeadBannerDisclaimer",
				description: "?bdHeadIntroDescription",
			},
		}
	});
	
	let disclaimerTemplate = `
		<div class="bd-head-banner-disclaimer-group">
			<bd-typography class="bd-head-banner-disclaimer"><ng-transclude-replace slot="title"></ng-transclude-replace></bd-typography>
			<bd-typography class="bd-head-banner-disclaimer">*Exclusions apply. <a href="#" ng-dialog="home-disclaimer-popup-{{disclaimerId}}" ng-dialog-class="ngdialog-theme-plain">See Details</a></bd-typography>
			<script type="text/ng-template" id="home-disclaimer-popup-{{disclaimerId}}" ng-transclude="content"></script>
		</div>
	`;
	window.bdApp.directive('bdHeadBannerDisclaimer', ($compile, $timeout, $templateCache) => ({
		replace: true,
		template: disclaimerTemplate,
		transclude: {
			title: "?bdDisclaimerTitle",
			content: "?bdDisclaimerContent",
		},
		link: ($scope) => {
			$scope.disclaimerId = $scope.$id;
			$timeout(() => {
				let html = document.getElementById(`home-disclaimer-popup-${$scope.disclaimerId}`).innerHTML;
				$templateCache.put(`home-disclaimer-popup-${$scope.disclaimerId}`, html);
			});
		}
	}));
	
	//#region Slots
	window.bdApp.directive('bdDisclaimerTitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	window.bdApp.directive('bdDisclaimerContent', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	window.bdApp.directive('bdHeadBannerContent', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	window.bdApp.directive('bdHeadBannerActions', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	//#endregion slots
	
	//#region Head intro
	let templateIntroTitle = `<ng-content-replace><bd-typography class="bd-head-banner-title"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`;
	window.bdApp.directive('bdHeadIntroTitle', () => ({template: templateIntroTitle, transclude: true, replace: true}));
	let templateIntroSubtitle = `<ng-content-replace><bd-typography class="bd-head-banner-subtitle"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`;
	window.bdApp.directive('bdHeadIntroSubtitle', () => ({template: templateIntroSubtitle, transclude: true, replace: true}));
	let templateIntroDescription = `<ng-content-replace><bd-typography class="bd-head-banner-description"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`;
	window.bdApp.directive('bdHeadIntroDescription', () => ({template: templateIntroDescription, transclude: true, replace: true}));
	//#endregion Head intro
	
	// let templateASlider = `<div class="bd-head-banner-slider"><bd-slider plugins="['classNames','wheelGestures']" slider="slider"><ng-transclude-replace></ng-transclude-replace></bd-slider></div>`;
	// window.bdApp.directive('bdHeadBannerSlider', () => ({
	// 	replace: true,
	// 	transclude: true,
	// 	template: templateASlider,
	// 	controller: ($scope, $element, $timeout) => {
	// 		$scope.$watch(() => $scope.slider, () => {
	// 			if(!$scope.slider) return;
	// 			$timeout(() => $scope.slider.reInit(), 1000);
	// 		});
	// 	}
	// }));
	
	let templateAItem = `
		<ng-content-replace>
			<bd-slide>
				<bd-display on-hide="(min-width: 768px)">
					<bd-stack class="bd-head-banner-wrapper">
						<bd-stack class="bd-head-banner-intro" flex-direction="column" align-items="center">
							<ng-transclude-replace slot="content"></ng-transclude-replace>
							<bd-collection-gallery-detail loading="eager" class="bd-head-banner-right" position="right" image-id="{{image}}" image-src="{{imageSrc}}"></bd-collection-gallery-detail>
							<bd-stack flex-direction="column" justify-content="center" align-items="center" class="bd-head-banner-actions">
								<ng-transclude-replace slot="actions"></ng-transclude-replace>
								<ng-transclude-replace ng-if="hasDisclaimer" slot="disclaimer"></ng-transclude-replace>
							</bd-stack>
						</bd-stack>
					</bd-stack>
				</bd-display>
				<bd-display on-visible="(min-width: 768px)" on-hide="(min-width: 1200px)">
					<bd-stack flex-direction="column" class="bd-head-banner-wrapper">
						<bd-stack class="bd-head-banner-intro" flex-direction="column">
							<ng-transclude-replace slot="content"></ng-transclude-replace>
							<bd-stack flex-direction="row" class="bd-head-banner-actions">
								<ng-transclude-replace slot="actions"></ng-transclude-replace>
							</bd-stack>
							<ng-transclude-replace ng-if="hasDisclaimer" slot="disclaimer"></ng-transclude-replace>
						</bd-stack>
						<bd-collection-gallery-detail loading="eager" class="bd-head-banner-right" variant="long" position="right" image-id="{{image}}" image-src="{{imageSrc}}"></bd-collection-gallery-detail>
					</bd-stack>
				</bd-display>
				<bd-display on-visible="(min-width: 1200px)">
					<bd-stack flex-direction="row" class="bd-head-banner-wrapper">
						<bd-stack class="bd-head-banner-intro" flex-direction="column">
							<ng-transclude-replace slot="content"></ng-transclude-replace>
							<bd-stack flex-direction="row" class="bd-head-banner-actions">
								<ng-transclude-replace slot="actions"></ng-transclude-replace>
							</bd-stack>
							<ng-transclude-replace ng-if="hasDisclaimer" slot="disclaimer"></ng-transclude-replace>
						</bd-stack>
						<bd-collection-gallery-detail loading="eager" class="bd-head-banner-right" variant="long" position="right" image-id="{{image}}" image-src="{{imageSrc}}"></bd-collection-gallery-detail>
					</bd-stack>
				</bd-display>
			</bd-slide>
		</ng-content-replace>
	`;
	window.bdApp.directive('bdHeadBannerItem', () => ({
		replace: true,
		template: templateAItem,
		scope: {image: "@", imageSrc: "@"},
		transclude: {
			actions: "?bdHeadBannerActions",
			content: "?bdHeadBannerContent",
			disclaimer: "?bdHeadBannerDisclaimer",
			description: "?bdHeadIntroDescription",
		},
		controller: ($scope, $transclude) => {
			// $scope.variant = $scope.variant.toLowerCase()
			$scope.hasDisclaimer = $transclude.isSlotFilled('disclaimer');
		},
	}));
})();
(function () {
	'use strict';

	let template = `
		<bd-slider-up options="sliderOptions" plugins="sliderPlugins" root-class="bd-hero-slider-root" container-class="bd-hero-slider"></bd-slider-up>
	`;

	const controller = ['$scope', function ($scope) {
		const autoplay = EmblaCarouselAutoplay({
			delay: $scope.delay ? $scope.delay : 5000,
			stopOnMouseEnter: true,
		});

		$scope.sliderPlugins = [
			autoplay,
			EmblaCarouselWheelGestures(),
		];

		$scope.sliderOptions = {
			loop: true,
			skipSnaps: false,
		};
	}];

	window.bdApp.directive('bdHeroSlider', ['$compile', '$timeout', ($compile, $timeout) => ({
		controller,
		transclude: true,
		scope: {delay: "@?"},
		link(scope, element, attributes, ctrl, linker) {
			const slider = angular.element(template);
			linker(scope, (copy, scope) => {
				slider.append(copy);
				const content = $compile(slider)(scope);
				$timeout(() => element.replaceWith(content));
			});
		}
	})]);
})()
;
(function () {
	'use strict';
	
	let templateModuleA = `
		<div class="bd-home-collection bd-home-collection-a">
			<bd-slider plugins="['classNames','wheelGestures']">
				<ng-transclude-replace></ng-transclude-replace>
			</bd-slider>
		</div>
	`;
	
	let templateModuleBC = `
		<div class="bd-home-collection bd-home-collection-{{variant}}">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	let templates = [{key: 'a', template: templateModuleA}, {key: 'b', template: templateModuleBC}, {key: 'c', template: templateModuleBC}];
	
	window.bdApp.directive('bdHomeCollections', () => ({
		replace: true,
		transclude: true,
		scope: {variant: "@"},
		template: ($element, $attribute) => ($attribute.variant)
			? templates.find(x => x.key === $attribute.variant).template
			: `variant is not set`,
	}))
	
	let templateModuleAItem = `
		<ng-content-replace>
			<bd-slide>
				<bd-display on-hide="(min-width:1024px)">
					<bd-stack flex-direction="column" class="bd-home-collection-item">
						<div class="bd-home-collection-item-top">
							<bd-collection-gallery-detail position="right" class="bd-home-collection-item-image" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
						</div>
						<div class="bd-home-collection-item-bottom">
							<bd-stack flex-direction="column" class="bd-home-collection-item-intro">
								<ng-transclude-replace slot="content"></ng-transclude-replace>
								<bd-stack flex-direction="column" class="bd-home-collection-item-actions">
									<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}" text-only="true"></bd-collection-variant>
									<bd-stack class="bd-home-collection-item-buttons bd-home-collection-item-actions-row" flex-direction="row">
										<ng-transclude-replace slot="actions"></ng-transclude-replace>
									</bd-stack>
								</bd-stack>
							</bd-stack>
						</div>
					</bd-stack>
				</bd-display>
				<bd-display on-visible="(min-width:1024px)">
					<bd-stack flex-direction="row" class="bd-home-collection-item">
						<bd-stack flex-direction="column" class="bd-home-collection-item-intro">
							<ng-transclude-replace slot="content"></ng-transclude-replace>
							<bd-stack flex-direction="column" class="bd-home-collection-item-actions">
								<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}" text-only="true"></bd-collection-variant>
								<bd-stack class="bd-home-collection-item-buttons bd-home-collection-item-actions-row" flex-direction="row">
									<ng-transclude-replace slot="actions"></ng-transclude-replace>
								</bd-stack>
							</bd-stack>
						</bd-stack>
						<bd-collection-gallery-detail variant="long" position="right" class="bd-home-collection-item-image" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
					</bd-stack>
				</bd-display>
			</bd-slide>
		</ng-content-replace>
	`;
	
	let templateModuleBItem = `
		<ng-content-replace>
			<bd-display on-hide="(min-width:1024px)">
				<bd-stack flex-direction="column" class="bd-home-collection-item">
					<div class="bd-home-collection-item-intro">
						<bd-collection-gallery-detail class="bd-home-collection-item-image" position="right" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
						<bd-stack class="bd-home-collection-item-content" flex-direction="column"><ng-transclude-replace slot="content"></ng-transclude-replace></bd-stack>
					</div>
					<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}"></bd-collection-variant>
					<bd-stack class="bd-home-collection-item-actions bd-home-collection-item-actions-row" flex-direction="row"><ng-transclude-replace slot="actions"></ng-transclude-replace></bd-stack>
				</bd-stack>
			</bd-display>
			<bd-display on-visible="(min-width:1024px)" on-hide="(min-width:1200px)">
				<bd-stack flex-direction="column" class="bd-home-collection-item">
					<bd-collection-gallery-detail class="bd-home-collection-item-image" variant="large" position="right" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
					<bd-stack flex-direction="row" class="bd-home-collection-item-intro">
						<bd-stack class="bd-home-collection-item-content" flex-direction="column"><ng-transclude-replace slot="content"></ng-transclude-replace></bd-stack>
						<bd-stack class="bd-home-collection-item-actions bd-home-collection-item-actions-column" flex-direction="column"><ng-transclude-replace slot="actions"></ng-transclude-replace></bd-stack>
					</bd-stack>
					<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}"></bd-collection-variant>
				</bd-stack>
			</bd-display>
			<bd-display on-visible="(min-width:1200px)">
				<bd-stack flex-direction="row" class="bd-home-collection-item">
					<bd-collection-gallery-detail class="bd-home-collection-item-image" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
					<bd-stack flex-direction="column" class="bd-home-collection-item-intro">
						<bd-stack flex-direction="row" align-items="center">
							<bd-stack class="bd-home-collection-item-content" flex-direction="column"><ng-transclude-replace slot="content"></ng-transclude-replace></bd-stack>
							<bd-stack class="bd-home-collection-item-actions bd-home-collection-item-actions-column" flex-direction="column"><ng-transclude-replace slot="actions"></ng-transclude-replace></bd-stack>
						</bd-stack>
						<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}"></bd-collection-variant>
					</bd-stack>
				</bd-stack>
			</bd-display>
		</ng-content-replace>
	`;
	
	let templateModuleCItem = `
		<ng-content-replace>
			<bd-display on-hide="(min-width:768px)">
				<bd-stack flex-direction="column" class="bd-home-collection-item">
					<div class="bd-home-collection-item-intro"><ng-transclude-replace slot="content"></ng-transclude-replace></div>
					<bd-collection-gallery-detail position="right" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
					<bd-stack class="bd-home-collection-item-actions" flex-direction="column">
						<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}" text-only="true"></bd-collection-variant>
						<bd-stack class="bd-home-collection-item-buttons bd-home-collection-item-actions-row" flex-direction="row"><ng-transclude-replace slot="actions"></ng-transclude-replace></bd-stack>
					</bd-stack>
				</bd-stack>
			</bd-display>
			<bd-display on-visible="(min-width:768px)">
				<div class="bd-home-collection-item">
					<bd-collection-gallery-detail variant="long" position="right" image-src="{{src}}" image-id="{{image}}"></bd-collection-gallery-detail>
					<div class="bd-home-collection-item-wrapper">
						<div class="bd-home-collection-item-intro">
							<bd-stack flex-direction="column" class="bd-home-collection-item-content">
								<ng-transclude-replace slot="content"></ng-transclude-replace>
								<bd-stack class="bd-home-collection-item-actions" flex-direction="column">
									<bd-collection-variant class="bd-home-collection-item-variants" collection="{{collection}}" text-only="true"></bd-collection-variant>
									<bd-stack class="bd-home-collection-item-buttons bd-home-collection-item-actions-row" flex-direction="row"><ng-transclude-replace slot="actions"></ng-transclude-replace></bd-stack>
								</bd-stack>
							</bd-stack>
						</div>
					</div>
				</div>
			</bd-display>
		</ng-content-replace>
	`;
	
	let itemTemplates = [{key: 'a', template: templateModuleAItem}, {key: 'b', template: templateModuleBItem}, {key: 'c', template: templateModuleCItem}];
	
	window.bdApp.directive('bdHomeCollectionItem', () => ({
		replace: true,
		template: ($elem) => {
			let variant = $elem.parent().attr('variant');
			return itemTemplates.find(x => x.key === variant).template;
		},
		transclude: {
			content: "?bdHomeCollectionItemContent",
			actions: "?bdHomeCollectionItemActions",
		},
		scope: {
			src: "@",
			image: "@",
			collection: "@",
		}
	}));
	
	window.bdApp.directive('bdHomeCollectionItemContent', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	
	window.bdApp.directive('bdHomeCollectionItemActions', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`,
	}));
	
	window.bdApp.directive('bdHomeCollectionItemTitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-home-collection-item-title"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`,
	}));
	
	window.bdApp.directive('bdHomeCollectionItemSubtitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-home-collection-item-subtitle"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`,
	}));
	
	window.bdApp.directive('bdHomeCollectionItemDescription', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-home-collection-item-description"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`,
	}));
})();
(function () {
	'use strict';

	const template = `
		<bd-slider-up container-class="bd-home-featured-slider" options="sliderOptions">
			<a ng-repeat="item in items" ng-href="{{item.href}}" class="bd-home-featured-card">
				<bd-image-detail class="bd-home-featured-card-image" image="item.image" width="1728"></bd-image-detail>
				<div class="bd-home-featured-card-content">
					<span class="bd-home-featured-card-title font-bold">{{item.header}}</span>
					<span class="bd-home-featured-card-subtitle">{{item.subtitle}}</span>
					<span class="bd-home-featured-card-link">Shop the Collection</span>
				</div>
			</a>
		</bd-slider-up>
	`;

	const controller = ['$scope', function (scope) {
		scope.sliderOptions = {
			dots: 'gap-8',
			skipSnaps: true,
			dot: 'rounded-dots',
		}
		this.items = scope.items = [];
		this.addItem = (item) => this.items.push(item);
	}];

	window.bdApp.directive('bdHomeFeaturedSlider', ['$compile', '$timeout', ($compile, $timeout) => ({
		transclude: true,
		controller: controller,
		link(scope, element, attributes, ctrl, linker) {
			linker(scope, (copy) => element.append(copy));
			const content = $compile(template)(scope);
			element.replaceWith(content);
		}
	})]);

	window.bdApp.directive('bdHomeFeaturedSliderItem', () => ({
		require: '^^bdHomeFeaturedSlider',
		link: (scope, element, attributes, ctrl) => ctrl.addItem({
			href: attributes.href,
			image: attributes.image,
			header: attributes.header,
			subtitle: attributes.subtitle,
		}),
	}));
})()
;
(function () {
	'use strict';
	
	let template = `
		<div class="bd-home-gallery">
			<bd-slider plugins="['classNames','wheelGestures']" options="options">
				<ng-transclude-replace></ng-transclude-replace>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdHomeGallery', () => ({
		template,
		scope: true,
		replace: true,
		transclude: true,
		controller: ($scope) => $scope.options = {
			dragFree: true,
			align: 'center',
			slidesToScroll: 1,
			breakpoints: {
				'(min-width: 768px)': {
					align: 'end',
					slidesToScroll: 2,
					containScroll: false,
				},
				'(min-width: 1024px)': {
					align: 'start',
					slidesToScroll: 2,
					containScroll: false,
				},
			}
		}
	}));
	
	let templateItem = `
		<ng-content-replace>
			<bd-slide class="bd-home-gallery-item">
				<bd-responsive-image width="1200" class="bd-home-gallery-item-image" image-src="{{src}}"></bd-responsive-image>
			</bd-slide>
		</ng-content-replace>
	`;
	
	window.bdApp.directive('bdHomeGalleryItem', () => ({
		replace: true,
		scope: {src: "@"},
		template: templateItem,
	}));
})();
(function () {
	'use strict'

	const sliderTemplate = `
		<div ng-show="!products" class="progress-enabled-local busy"></div>
		<bd-slider-up ng-show="products.length" container-class="bd-home-product-slider" options="sliderOptions" plugins="sliderPlugins">
			<a class="bd-product-card" ng-href="{{item.href}}" ng-repeat="item in products">
				<div class="bd-product-card__image skeleton" ng-class="{'has-alt-image': item.altImage}">
					<bd-image class="plp-item-alt-img" ng-if="item.altImage" src="{{item.altImage}}" width="500" height="500"></bd-image>
					<bd-image class="plp-item-main-img" src="{{item.image}}" width="500" height="500"></bd-image>
				</div>
				<span class="font-bold">{{item.productSeries}}</span>
				<span>{{item.size}} {{item.materialFinish}} {{item.materialType}} {{item.materialCategory}}</span>
			</a>
		</bd-slider-up>
	`;

	const sliderController = ['$scope', function (scope) {
		scope.sliderOptions = {
			dots: false,
			align: 'center',
			skipSnaps: true,
			slidesToScroll: 'auto',
		};

		scope.sliderPlugins = [EmblaCarouselWheelGestures()];

		this.list = scope.list = [];
		this.items = scope.items = [];
		this.addItem = (item) => scope.items.push(item);
	}];

	window.bdApp.directive('bdHomeProductSlider', ['$api', '$compile', '$timeout', 'appSettings', '$requestBuilders', ($api, $compile, $timeout, $settings, $requestBuilders) => ({
		scope: true,
		transclude: true,
		controller: sliderController,
		link(scope, element, attributes, ctrl, linker) {

			if (attributes.auto === 'true') {
				scope.sliderOptions.buttons = false;
				scope.sliderPlugins.push(EmblaCarouselAutoScroll({
					speed: 0.5,
					startDelay: 100,
					stopOnMouseEnter: false,
					stopOnInteraction: false,
				}));
			}

			const content = $compile(sliderTemplate)(scope);
			$timeout(() => element.replaceWith(content));

			const request = $requestBuilders.$webproductListRequestBuilder();
			if (attributes.sort) request.setSort(attributes.sort);
			if (attributes.query) request.parseQuery(attributes.query);
			if (attributes.category) request.addCategory(attributes.category);
			request.addParameter('pageSize', attributes.size ? attributes.size : 10);
			request.addParameter('pageIndex', attributes.page ? attributes.page : 1);

			const render = (request) => {
				$api.$webproduct.list(request.make()).then((result) => {
					if (result.value) return result.value.products
					else throw 'Products Not Found';
				}).then((data) => {
					scope.products = data.map((item) => ({
						...item,
						image: `/cdn-bedrosian/assets/products/hiresimages/${item.imageName}`,
						altImage: item.alternativeImageUrl ? item.alternativeImageUrl.replace(/(http:|https:|)\/\/res(-\d*)?\./g, 'https://res.').replace(/\/t_[^/]+/g, '') : null,
						href: $settings.getSecureUrl(`product/detail/${item.urlFriendlyStyleName ? item.urlFriendlyStyleName : ''}?itemNo=${item.productCode}`, true),
					}));
				})
			}

			$timeout(() => render(request), 0);

			linker(scope, (copy) => element.append(copy));
		}
	})]);

	window.bdApp.directive('bdHomeProductSliderItem', () => ({
		scope: true,
		transclude: true,
		require: '^^bdHomeProductSlider',
		link(scope, element, attribute, ctrl) {
			ctrl.addItem(attribute.itemNo);
		}
	}));
})()
;
(function () {
	'use strict'

	const template = `
		<bd-slider-up container-class="bd-home-sample-slider" options="sliderOptions">
			<a ng-repeat="item in items" ng-href="{{item.href}}" target="_blank" class="bd-home-sample-item">
				<img ng-src="{{item.image}}" src="" alt="" aria-hidden="true"/>
			</a>
		</bd-slider-up>
	`;

	const sampleSliderController = ['$scope', function ($scope) {
		$scope.sliderOptions = {
			dots: false,
			skipSnaps: true,
			breakpoints: {
				'(min-width: 768px)': {
					active: false,
				}
			}
		};

		this.items = $scope.items = [];
		this.addItem = (item) => this.items.push(item);
	}];

	window.bdApp.directive('bdHomeSampleSlider', ['$compile', '$timeout', ($compile, $timeout) => ({
		transclude: true,
		controller: sampleSliderController,
		link(scope, element, attribute, ctrl, linker) {
			const content = $compile(template)(scope);
			$timeout(() => element.replaceWith(content));
			linker(scope, (copy) => element.append(copy));
		}
	})]);

	window.bdApp.directive('bdHomeSampleItem', ['appSettings', (settings) => ({
		require: '^^bdHomeSampleSlider',
		link(scope, element, attributes, ctrl) {
			ctrl.addItem({
				image: attributes.image,
				href: settings.getSecureUrl(`product/detail/?itemNo=${attributes.itemNo}&sample=true`, true),
			});
		}
	})]);
})()
;
(function () {
	'use strict';

	let template = `
		<section class="bd-main-section" ng-class="class">
			<ng-transclude-replace></ng-transclude-replace>
		</section>
	`;

	window.bdApp.directive('bdHomeSection', () => ({
		template,
		replace: true,
		transclude: true,
		scope: {variant: "@"},
		controller: ($scope) => {
			$scope.class = [];
			if ($scope.variant) $scope.class.push(`bd-main-section-${$scope.variant}`);
		}
	}));

	let wrapperTemplate = `
		<div class="bd-main-wrapper">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;

	window.bdApp.directive('bdHomeWrapper', () => ({
		replace: true,
		transclude: true,
		template: wrapperTemplate,
	}))
})();
;
(function () {
	'use strict';

	const template = `
		<div class="bd-home-selector">
			<div class="bd-home-selector__title">
				<h2>{{header}}</h2>
				<bd-selector ng-model="selected" options="items"></bd-selector>
			</div>
			<div class="bd-home-selector__container" role="region">
				<!--slot@container-->
			</div>
		</div>
	`;

	const selectorController = ['$scope', function ($scope) {
		this.items = $scope.items = [];
		this.addItem = (item) => this.items.push(item);
	}];

	window.bdApp.directive('bdHomeSelector', ['$parse', '$compile', '$timeout', ($parse, $compile, $timeout) => ({
		scope: true,
		transclude: true,
		controller: selectorController,
		link(scope, element, attributes, $ctrl, linker) {
			scope.header = attributes.header;

			const root = $compile(template)(scope);
			$timeout(() => element.replaceWith(root), 0);

			scope.$watchCollection('items', (value) => {
				if (!value || !value.length) return;
				scope.selected = value[0].value;
			});

			scope.$watch('selected', (value) => {
				if (!value || !scope.items || !scope.items.length) return;
				const item = scope.items.find(x => x.value === value);
				item.linker(item.inner, (copy) => {
					const container = root.find('[role="region"]');
					container.empty().append(copy);
				});
			});

			linker(scope, (copy) => element.append(copy));
		}
	})]);

	window.bdApp.directive('bdHomeSelectorItem', ['$compile', ($compile) => ({
		scope: true,
		transclude: true,
		require: '^^bdHomeSelector',
		link(scope, element, attributes, ctrl, linker) {
			const item = {
				disabled: attributes.disabled,
				value: attributes.value,
				linker: linker,
				inner: scope,
			};
			ctrl.addItem(item);
		}
	})]);
})()

;
(function () {
	'use strict';
	
	let template = `
		<div class="bd-home-skinny-banner bd-home-skinny-banner-{{variant}}">
			<bd-slider plugins="['classNames','wheelGestures']" options="{dots:false}"><ng-transclude-replace></ng-transclude-replace></bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdHomeSkinnyBanner', () => ({
		template,
		replace: true,
		transclude: true,
		scope: {
			variant: "@",
		},
		// transclude: {
		// 	content: '?bdHomeSkinnyBannerContent',
		// 	disclaimer: '?bdHomeSkinnyBannerDisclaimer',
		// },
		// link: ($scope, $element) => {
		// 	angular.element(window).bind('scroll', () => {
		// 		let _class = 'bd-home-skinny-banner-fixed';
		// 		if(window.pageYOffset > 0) $element.addClass(_class);
		// 		else $element.removeClass(_class);
		// 	});
		// }
	}));
	
	let itemTemplate = `
		<ng-content-replace>
			<bd-slide>
				<a ng-href="{{href}}">
					<div class="bd-home-skinny-banner-content"><ng-transclude-replace slot="content"></ng-transclude-replace></div>
					<ng-transclude-replace slot="disclaimer"></ng-transclude-replace>
				</a>
			</bd-slide>
		</ng-content-replace>
	`;
	
	window.bdApp.directive('bdHomeSkinnyBannerItem', () => ({
		replace: true,
		scope: {href: "@"},
		template: itemTemplate,
		transclude: {
			content: '?bdHomeSkinnyBannerContent',
			disclaimer: '?bdHomeSkinnyBannerDisclaimer',
		},
	}))
	
	window.bdApp.directive('bdHomeSkinnyBannerContent', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><ng-transclude-replace></ng-transclude-replace></ng-content-replace>`
	}))
	
	let disclaimerTemplate = `
		<ng-content-replace>
			<span>| <a class="bd-link" ng-click="showDisclaimer()">See Details</a></span>
			<script id="bd-home-skinny-disclaimer-{{$id}}" ng-transclude></script>
		</ng-content-replace>
	`;
	
	window.bdApp.directive('bdHomeSkinnyBannerDisclaimer', (ngDialog) => ({
		replace: true,
		transclude: true,
		template: disclaimerTemplate,
		controller: ($scope, ngDialog) => {
			$scope.showDisclaimer = () => {
				let template = document.getElementById('bd-home-skinny-disclaimer-' + $scope.$id).innerHTML;
				ngDialog.open({template, plain: true, showClose: false, className:'ngdialog-theme-plain ngdialog-theme-disclaimer'});
			}
		}
	}));
})();
(function() {
	'use strict';
	
	window.bdApp.directive('bdHomeSectionTitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-stack flex-direction="column" class="bd-home-section-title"><ng-transclude-replace></ng-transclude-replace></bd-stack></ng-content-replace>`
	}))
	
	window.bdApp.directive('bdHomeTitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-home-title"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}));
	
	window.bdApp.directive('bdHomeSubtitle', () => ({
		replace: true,
		transclude: true,
		template: `<ng-content-replace><bd-typography class="bd-home-subtitle"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>`
	}));
})();
(function () {
	'use strict';
	
	let template = `
		<div class="bd-hover-cards">
			<bd-slider plugins="['classNames','wheelGestures']">
				<ng-transclude-replace></ng-transclude-replace>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdHoverCards', () => ({
		template,
		replace: true,
		transclude: true,
	}));
	
	let templateHoverCardsItem = `
		<ng-content-replace>
			<bd-slide>
				<a ng-href="{{href}}" class="bd-hover-cards-item">
					<bd-responsive-image width="600" image-src="{{image}}"></bd-responsive-image>
					<span class="bd-hover-cards-item-content">
						<ng-transclude-replace></ng-transclude-replace>
					</span>
				</a>
			</bd-slide>
		</ng-content-replace>
	`;
	
	window.bdApp.directive('bdHoverCardsItem', () => ({
		replace: true,
		transclude: true,
		scope: {href: "@", image: "@"},
		template: templateHoverCardsItem,
		controller: ($scope) => $scope.breakpoints = {'(min-width: 0px)': 600},
	}))
	
	window.bdApp.directive('bdHoverCardsItemTitle', () => ({
		replace: true,
		transclude: true,
		template: '<ng-content-replace><bd-typography class="bd-hover-cards-item-title"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>',
	}));
	
	window.bdApp.directive('bdHoverCardsItemSubtitle', () => ({
		replace: true,
		transclude: true,
		template: '<ng-content-replace><bd-typography class="bd-hover-cards-item-subtitle"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>',
	}));
	
	window.bdApp.directive('bdHoverCardsItemDescription', () => ({
		replace: true,
		transclude: true,
		template: '<ng-content-replace><bd-typography class="bd-hover-cards-item-description"><ng-transclude-replace></ng-transclude-replace></bd-typography></ng-content-replace>',
	}));
})();
(function () {
	'use strict';

	window.bdApp.value('icon-bookmark', `
		<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 16 24" fill="none">
			<path d="M2.5 22.9333V1.93329H13.5V22.9333L8 17.0102L2.5 22.9333Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
		</svg>
	`);

	window.bdApp.value('icon-trash', `
		<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 28 23" fill="none">
			<path d="M9.5 10.9333L10.5 17.4333M18.5 10.9333L17.5 17.4333M3 6.43329H8M24.5 6.43329H19.5M8 6.43329H5L8 21.9333H19.5L23 6.43329H19.5M8 6.43329L9.5 1.93329H18L19.5 6.43329M8 6.43329H19.5M14 10.9333V17.4333" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
		</svg>
	`);

	window.bdApp.value('icon-download', `
		<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 26 27" fill="none">
			<path d="M1 17.8921L1 25.7089L25 25.7087V17.892" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
			<path d="M20.3845 11.7408L13.4614 18.0153M13.4614 18.0153L6.53837 11.7408M13.4614 18.0153L13.4614 1.13943" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
		</svg>
	`);

	window.bdApp.value('icon-search', `
		<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" fill="none">
			<path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
			<path d="M20.9999 21.0004L16.6499 16.6504" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
		</svg>
	`);

	window.bdApp.value('icon-x-cross', `
		<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 11 11" fill="none">
			<path fill-rule="evenodd" clip-rule="evenodd" d="M2.01403 0.592563C1.62351 0.202039 0.990344 0.202039 0.59982 0.592563C0.209295 0.983087 0.209295 1.61625 0.59982 2.00678L3.77835 5.1853L0.592741 8.37091C0.202216 8.76143 0.202217 9.3946 0.592741 9.78512C0.983265 10.1756 1.61643 10.1756 2.00695 9.78512L5.19256 6.59952L8.37829 9.78524C8.76881 10.1758 9.40198 10.1758 9.7925 9.78524C10.183 9.39472 10.183 8.76155 9.7925 8.37103L6.60677 5.1853L9.78542 2.00666C10.1759 1.61613 10.1759 0.982967 9.78542 0.592443C9.3949 0.201919 8.76173 0.201918 8.37121 0.592443L5.19256 3.77109L2.01403 0.592563Z" fill="currentColor"/>
		</svg>
	`);

	window.bdApp.directive('bdIcon', ['$injector', function (injector) {
		return {
			scope: false,
			replace: true,
			template: `<span class="bd-icon"></span>`,
			compile(element) {
				const name = element.data('name');
				const key = `icon-${name}`;
				if (name && injector.has(key)) {
					let svg = injector.get(key);
					let icon = angular.element(svg);
					element.append(icon);
				} else {
					element.remove();
				}
			}
		}
	}]);
})()
;
(function () {
	'use strict';

	let template = `
		<div class="bd-image-detail" ng-init="hovered=false" ng-mouseenter="hovered=true" ng-mouseleave="hovered=false">
			<bd-image src="{{src}}" width="width" height="height" sizes="sizes"></bd-image>
			<div class="bd-image-detail-products" ng-class="{'bd-image-detail-products-active': active, 'bd-image-detail-products-hovered': hovered}" ng-if="products.length > 0">
				<div class="bd-image-detail-products-wrapper">
					<a ng-repeat="product in products" class="bd-image-detail-link" ng-href="{{product.href}}">
						<bd-image src="{{product.src}}" width="70" height="70" loading="eager"></bd-image>
						<span>{{product.title}}</span>
					</a>
				</div>
				<div class="bd-image-detail-close" ng-click="toggleProducts($event)">
					<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
						<path d="M6 1C6 0.447716 6.44772 0 7 0C7.55228 0 8 0.447715 8 1V13C8 13.5523 7.55228 14 7 14C6.44772 14 6 13.5523 6 13V1Z" fill="#626262"/>
						<path d="M13 6C13.5523 6 14 6.44772 14 7C14 7.55229 13.5523 8 13 8L1 8C0.447716 8 -6.78525e-08 7.55228 -4.37114e-08 7C-1.95703e-08 6.44771 0.447716 6 1 6L13 6Z" fill="#626262"/>
					</svg>
				</div>
				<div class="bd-image-detail-button" ng-click="toggleProducts($event)">
					<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
						<path class="vertical-icon-plank" d="M6 1C6 0.447716 6.44772 0 7 0C7.55228 0 8 0.447715 8 1V13C8 13.5523 7.55228 14 7 14C6.44772 14 6 13.5523 6 13V1Z" fill="#626262"/>
						<path d="M13 6C13.5523 6 14 6.44772 14 7C14 7.55229 13.5523 8 13 8L1 8C0.447716 8 -6.78525e-08 7.55228 -4.37114e-08 7C-1.95703e-08 6.44771 0.447716 6 1 6L13 6Z" fill="#626262"/>
					</svg>
					<span>Shop this look</span>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdImageDetail', ($api, $parse, $compile, $timeout, appSettings) => {
		return {
			template,
			scope: false,
			replace: true,
			controller($scope, $attrs) {
				$scope.src = ($parse($attrs.image))($scope) || ($parse($attrs.$attr.image))($attrs);
				$scope.sizes = ($parse($attrs.sizes))($scope) || ($parse($attrs.$attr.sizes))($attrs);
				$scope.width = ($parse($attrs.width))($scope) || ($parse($attrs.$attr.width))($attrs);
				$scope.height = ($parse($attrs.height))($scope) || ($parse($attrs.$attr.height))($attrs);
				$scope.products = ($parse($attrs.products))($scope) || ($parse($attrs.$attr.products))($attrs);

				$scope.toggleProducts = function ($event) {
					$event.preventDefault();
					$event.stopPropagation();
					$scope.active = !$scope.active;
				};

				if (!/[https?]*:?\/\/.*$/.test($scope.src)) {
					let {groups: {collection, src}} = $scope.src.match(/(?<collection>[^-]+)-(?<src>[^\s]+)$/);
					if (collection && src) $scope.src = `installation_shots/${collection}/${src.replace(/-/g, '_')}`;
				}

				if (!$scope.products) {
					let reg = /(installation_shots)\/(?<collection>.+)\/(?<src>.+)$/;
					if (!reg.test($scope.src)) return;
					let {groups: {collection, src}} = $scope.src.match(reg);
					let imageId = `${decodeURI(collection)}-${src}`.replace(/[\s|\_]/g, '-').toLowerCase();
					$api.$gallery.detail(imageId).then(res => {
						if (!res.value) return;
						$scope.src = res.value.largeImageSrc.replace(/(http:|https:|)\/\/res(-\d*)?\./g, 'https://res.').replace(/\/t_[^/]+/g, '');
						$scope.products = res.value.products.map(product => ({
							...product,
							href: appSettings.getSecureUrl(`product/detail/?itemNo=${product.code}`, true)
						}));
					});
				}
			}
		}
	});
})()
;
(function () {
	'use strict';

	// Common screen widths. These will be filtered
	// according to the image size and layout
	const DEFAULT_RESOLUTIONS = [
		6016, // 6K
		5120, // 5K
		4480, // 4.5K
		3840, // 4K
		3200, // QHD+
		2560, // WQXGA
		2048, // QXGA
		1920, // 1080p
		1668, // Various iPads
		1280, // 720p
		1080, // iPhone 6-8 Plus
		960, // older horizontal phones
		828, // iPhone XR/11
		750, // iPhone 6-8
		640, // older and lower-end phones
	];

	window.bdApp.directive('bdImage', ['$parse', '$filter', '$compile', '$timeout', ($parse, $filter, $compile, $timeout) => {
		function getBreakpoints(width, resolutions = DEFAULT_RESOLUTIONS) {
			let doubleWidth = width * 2;
			if (!width) return resolutions;
			return [
				width,
				doubleWidth,
				...resolutions.filter(x => x < doubleWidth),
			];
		}

		function getSources(src, config) {
			let aspectHeight = 0;
			if (config.height) aspectHeight = config.height / config.width;
			let breakpoints = getBreakpoints(config.width);
			return breakpoints.sort((a, b) => a - b).map(x => {
				if (aspectHeight) config.height = x * aspectHeight;
				let url = ($filter('cloudinaryUp'))(src, {
					...config,
					width: x,
					quality: 70,
					crop: 'lfill',
					fetchFormat: 'auto',
					rawTransformation: ['d_assets:bd_default.auto'],
				});
				return {
					url,
					width: x,
					source: `${url} ${x}w`,
				};
			});
		}

		return {
			scope: {
				src: "@",
				alt: "@",
				sizes: "=",
				width: "=",
				height: "=",
			},
			link(scope, element, attributes) {
				const inner = scope.$new();

				let tag = angular.element('<img class="skeleton" alt="{{alt}}" sizes="{{sizes}}" ng-srcset="{{srcset}}" decode="{{decode}}">');
				tag.on('load', () => tag.off('load') && tag.removeClass('skeleton'));
				tag.addClass(attributes.class);

				scope.$watch('src', (value) => {
					const width = scope.width;
					const height = scope.height;
					tag.css('max-width', `${width}px`);
					inner.decode = attributes.decode ? attributes.decode : 'async';
					inner.sizes ||= width ? `(min-width:${width}px) ${width}px, 100vw` : '100vw';
					inner.srcset = getSources(value, {width, height}).map(x => x.source).join(',');
				});

				const content = $compile(tag)(inner);
				element.replaceWith(content);
			}
		}
	}]);
})()
;
(function () {
	'use strict';
	
	let template = `
		<div class="bd-master-ribbon">
			<bd-slider class="bd-master-ribbon-slider" options="sliderOptions" plugins="sliderPlugins">
				<ng-transclude-replace></ng-transclude-replace>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdMasterRibbon', () => ({
		template,
		scope: true,
		transclude: true,
		controller: ($scope) => {
			$scope.sliderPlugins = ['autoplay', 'wheelGestures'];
			
			$scope.sliderOptions = {
				loop: true,
				dots: false,
				watchDrag: false,
				showButtons: false,
			};
		}
	}));
	
	let templateItem = `
		<ng-content-replace><bd-slide class="bd-master-ribbon-item"><ng-transclude-replace></ng-transclude-replace></bd-slide></ng-content-replace>
	`;
	
	window.bdApp.directive('bdMasterRibbonItem', () => ({
		replace: true,
		transclude: true,
		template: templateItem,
	}));
})();
(function () {
	'use strict';

	const template = `
		<div class="bd-menu-large">
			<ul class="bd-menu-large-list">
				<li class="bd-menu-large-item" ng-class="{'clearance': item.isClearance, 'has-child': item.hasChild}" ng-repeat="item in menu track by item.title" ng-mouseover="open($event, item)">
					<span ng-if="item.hasChild">{{item.title}}</span>
					<a ng-if="!item.hasChild" class="none-link" href="{{item.url}}">{{item.title}}</a>
				</li>
			</ul>
		</div>
	`;

	const megaTemplate = `
		<div class="bd-menu-large-mega bd-menu-large-mega-in">
			<div class="bd-menu-large-mega-content">
				<div class="bd-menu-large-mega-content-wrapper">
					<ul class="bd-menu-large-mega-list" ng-class="{'border-left-none': item.isInspiration}" ng-repeat="item in menu track by item.title">
						<li ng-if="!item.image && $index > 0" class="bd-menu-large-mega-list-title">
							<span>{{item.title}}</span>
						</li>
						<li ng-if="item.image" class="bd-menu-large-mega-list-item">
							<a class="w-full" ng-class="{'nav-menu-inspiration-item': item.isInspiration, 'none-link': !item.isInspiration}" ng-href="{{item.url}}">
								<img alt="shop this look" class="w-full rounded-xl mb-2" aria-hidden="true" ng-if="item.image" ng-src="{{item.image}}" />
								<span>{{item.title}}</span>
							</a>
						</li>
						<li class="bd-menu-large-mega-list-item" ng-class="{'border-left-none': child.isInspiration}" ng-repeat="child in item.children track by child.title">
							<a class="w-full" ng-class="{'nav-menu-inspiration-item': child.isInspiration, 'none-link': !child.isInspiration}" ng-href="{{child.url}}">
								<img alt="shop this look" class="w-full rounded-xl mb-2" aria-hidden="true" ng-if="child.image" ng-src="{{child.image}}" />
								<span>{{child.title}}</span>
							</a>
						</li>
					</ul>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdMenuLarge', ['$compile', '$timeout', ($compile, $timeout) => ({
		template,
		scope: true,
		compile(element, attrs) {
			return function (scope) {
				scope.currentItem = null;

				const children = element.children();
				element.replaceWith($compile(children)(scope));

				const elementClass = attrs.class;
				children.addClass(elementClass);

				const body = angular.element('body');

				const debouncedOpen = _.debounce((event, item) => {
					$timeout(() => {
						scope.$apply(() => {
							if (!item.hasChild) return;

							const target = event.currentTarget;
							const top = target.offsetTop + target.offsetHeight;
							const height = window.outerHeight - top

							const childScope = scope.$new(true);
							childScope.menu = item.children;

							const element = $compile(megaTemplate)(childScope);
							element.css({top, height});
							body.append(element);

							scope.currentItem = {
								scope: childScope,
								element,
								item,
							};
						})
					})
				}, 300);

				scope.open = function (event, item) {
					if (scope.currentItem && scope.currentItem.item === item) return;
					close().then(() => debouncedOpen(event, item));
				};

				const close = () => new Promise((resolve) => {
					debouncedOpen.cancel();
					if (!scope.currentItem) return resolve();
					scope.currentItem.element.addClass('bd-menu-large-mega-out');
					scope.currentItem.element.removeClass('bd-menu-large-mega-in');
					$timeout(() => {
						if (!scope.currentItem) return resolve();
						scope.currentItem.scope.$destroy();
						scope.currentItem.element.remove();
						scope.currentItem = null;
						return resolve();
					}, 300);
				});

				const debouncedClose = _.debounce(close, 500);

				angular.element(document).on('mouseover', function (event) {
					debouncedClose.cancel();

					const target = angular.element(event.target)[0];
					const isOverMainMenu = children[0].contains(target);
					const isOverSubMenu = scope.currentItem
						&& scope.currentItem.element[0] !== target
						&& scope.currentItem.element[0].contains(target);

					if (!isOverMainMenu && !isOverSubMenu) scope.$apply(() => {
						debouncedOpen.cancel();
						debouncedClose()
					});
				});
			};
		}
	})]);
})();
;
(function () {
	'use strict';

	const menuContentTemplate = `
		<div class="bd-menu-small-content bd-menu-small-content-in">
			<ul class="bd-menu-small-list">
				<li class="bd-menu-small-item text-md parent back" ng-click="back()">
					<span>{{ data.header ? data.header + ' / ' : '' }}<span class="text-nowrap">{{ data.item.title }}</span></span>
				</li>
				<li class="bd-menu-small-item text-base parent has-child" ng-class="{'clearance': item.isClearance}" ng-click="onItemClick(item)" ng-repeat="item in data.menu | filter: {hasChild: true}">
					<span>{{item.title}}</span>
				</li>
			</ul>
			<ul class="bd-menu-small-list">
				<li class="bd-menu-small-item text-base" ng-click="onItemClick(item)" ng-repeat="item in data.menu | filter: {hasChild: false}">
					<a class="w-full" ng-class="{'clearance': item.isClearance, 'nav-menu-inspiration-item': item.isInspiration, 'none-link': !item.isInspiration}" ng-href="{{item.url}}">
						<img alt="shop this look" class="w-full rounded-xl mb-2" aria-hidden="true" ng-if="item.image" ng-src="{{item.image}}" />
						<span ng-class="{'self-center': item.image}">{{item.title}}</span>
					</a>
				</li>
			</ul>
		</div>
	`;

	const menuLocationsTemplate = `
		<div class="bd-menu-small-content bd-menu-small-content-in progress-enabled" ng-class="{busy: !data.locations}">
			<ul class="bd-menu-small-list">
				<li class="bd-menu-small-item text-md parent back" ng-click="back()">
					<span>My Location</span>
				</li>
				<li class="bd-menu-small-item text-base" ng-click="onLocationItemClick(location)" ng-repeat="location in data.locations">
					<span>{{location.Name}}</span>
				</li>
			</ul>
		</div>
	`;

	const menuAccountTemplate = `
		<div class="bd-menu-small-content bd-menu-small-content-in">
			<ul class="bd-menu-small-list">
				<li class="bd-menu-small-item text-md parent back" ng-click="back()">
					<span>My Account</span>
				</li>
				<li class="bd-menu-small-item text-base" ng-repeat="item in data.menu">
					<a class="none-link" href="{{item.url}}">{{item.title}}</a>
				</li>
			</ul>
		</div>
	`;

	const template = `
		<button class="site-header-menu-button hamburger" ng-click="open()">Open Drawer</button>
		<bd-drawer open="active" close="onDrawerClose()" ref="drawer">
			<div class="bd-menu-small-wrapper progress-enabled" ng-class="{busy: data.busy}" data-menu-container>
				<div class="bd-menu-small-content">
					<ul class="bd-menu-small-list">
						<li class="bd-menu-small-item text-md parent" ng-class="{'clearance': item.isClearance, 'has-child': item.hasChild}" ng-click="onItemClick(item)" ng-repeat="item in menu track by item.title">
							<span>{{item.title}}</span>
						</li>
					</ul>
					<ul class="bd-menu-small-actions">
						<li class="bd-menu-small-item text-md parent">
							<a class="none-link" ng-href="{{locationsUrl}}">Store Locations</a>
						</li>
						<li ng-click="onLocationsMenuClick()" class="bd-menu-small-item text-md parent has-child">
							<span>My Location</span>
						</li>
						<li ng-click="onAccountMenuClick()" class="bd-menu-small-item text-md parent has-child">
							<span>My Account</span>
						</li>
					</ul>
				</div>
			</div>
		</bd-drawer>
	`;

	window.bdApp.directive('bdMenuSmall', ['$compile', '$timeout', 'branchLocatorService', ($compile, $timeout, branchLocatorService) => ({
		template,
		scope: true,
		compile(element, attrs) {
			return function (scope) {
				scope.active = false;

				const items = [];

				const children = element.children();
				element.replaceWith($compile(children)(scope));

				const elementClass = attrs.class;
				children.addClass(elementClass);

				scope.open = () => scope.active = true;

				scope.onItemClick = (item) => {
					if (item.url && !item.hasChild) {
						window.location = item.url;
						scope.active = false;
						return;
					}
					const childScope = scope.$new(false);
					childScope.data = {
						item,
						menu: item.children,
						header: items.map(item => item.item.title).join(' / '),
					};
					const content = ($compile(menuContentTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
						item,
					});
				}

				scope.onLocationsMenuClick = () => {
					const childScope = scope.$new(false);
					childScope.data = {
						locations: scope.locations,
						currentLocation: 'California',
					};
					const content = ($compile(menuLocationsTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
					});
				}

				scope.onLocationItemClick = (item) => {
					scope.data = {busy: true};
					branchLocatorService.ChooseStateByAbbreviation(item.Abbreviation)
						.then(() => window.location.reload())
						.then(() => scope.active = false);
				};

				scope.onAccountMenuClick = () => {
					const childScope = scope.$new(false);
					childScope.data = {menu: scope.accountMenu};
					const content = ($compile(menuAccountTemplate))(childScope);
					const container = angular.element(document.querySelector('[data-menu-container]'));
					container.append(content);
					items.push({
						scope: childScope,
						page: content,
					});
				}

				scope.back = () => {
					const item = items.pop();
					item.page.addClass('bd-menu-small-content-out');
					item.page.removeClass('bd-menu-small-content-in');
					$timeout(() => {
						item.scope.$destroy();
						item.page.remove();
					}, 299);
				}

				scope.onDrawerClose = () => {
					while (items.length > 0) {
						const item = items.pop();
						item.scope.$destroy();
						item.page.remove();
					}
				};
			}
		},
	})])
})()
;
(function() {
	'use strict';
	
	let template = `
		<div class="bd-navigation-tab">
			<bd-slider no-animate="true" plugins="['classNames','wheelGestures']"><ng-transclude-replace></ng-transclude-replace></bd-slider>
		</div>
	`;
	
	window.bdApp.directive('bdNavigationTab', () => ({
		template,
		replace: true,
		transclude: true,
	}));
	
	let templateNavigationCard = `
		<div ng-content-replace>
			<bd-slide>
				<a class="bd-navigation-card" ng-href="{{href}}">
					<bd-responsive-image width="600" image-src="{{image}}"></bd-responsive-image>
					<span>{{title}}</span>
				</a>
			</bd-slide>
		</div>
	`;
	
	window.bdApp.directive('bdNavigationCard', () => ({
		replace: true,
		template: templateNavigationCard,
		scope: {image: "@", href: "@", title: "@"},
		controller: ($scope) => $scope.breakpoints = {'(min-width: 0px)': 500},
	}))
})();
(function() {
	'use strict';
	
	let template = `
		<div class="skeletron-loader" aria-hidden="true">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`
	
	window.bdApp.directive('bdPreloader', () => ({
		template,
		replace: true,
		transclude: true,
		scope: { template: "=" },
		controller: ($scope, $compile, $element) => {
			if($scope.template) {
				let compile = $compile($scope.template)($scope);
				$element.append(compile);
			}
		}
	}))
})();
(function () {
	'use strict';

	window.bdApp.directive('bdProductListBanner', ($compile) => ({
		scope: true,
		transclude: true,
		compile(element, attrs, linker) {
			let zone = attrs.zone;
			let row = parseInt(attrs.row) || 3;
			return (scope) => {
				let inner = scope.$new(false);
				let root = angular.element('<div class="bd-product-list-banner"></div>');

				let breakpoints = [
					{
						count: 4,
						media: '(min-width: 1920px)',
					},
					{
						count: 4,
						media: '(min-width: 768px)',
					},
					{
						count: 2,
						media: '(max-width: 768px)',
					},
				];

				const update = () => {
					let counter = breakpoints.find(x => window.matchMedia(x.media).matches);
					let order = (counter) ? counter.count * (row - 1) : 3;
					root.css('order', order);
				}

				update();

				return linker(inner, (clone) => {
					const hasContent = Array.from(clone).some(x => x.nodeType !== Node.TEXT_NODE);
					if (hasContent) {
						root.append(clone);
						element.replaceWith(root);
						angular.element(window).on('resize', update);
					} else element.remove();
				});
			}
		}
	}))
})()
;
(function () {
	'use strict';

	const template = `
		<div ng-show="items.length || useSkeleton" ng-class="rootClass" class="">
			<p ng-class="titleClass" class="">{{header}}</p>
			<bd-slider-up ng-if="items.length" ng-class="containerClass" class="" options="{skipSnaps:true,breakpoints:{'(min-width: 768px)':{slidesToScroll:2}}}">
				<a ng-href="{{item.href}}" target="_self" ng-class="itemClass" class="bd-recommendations-item" ng-repeat="item in items track by $index">
					<div class="bd-recommendations-image skeleton"><img alt="{{item.name}}" ng-src="{{item.image | cloudinary}}" /></div>
					<span class="bd-recommendations-item-title">{{item.name}}</span>
					<span class="bd-recommendations-item-price" ng-if="item.currentPrice > 0">{{item.currentPrice | currency}} / {{item.uom}}</span>
				</a>
			</bd-slider-up>
			<div ng-if="!items.length && useSkeleton" ng-class="containerClass" style="display:flex;flex-flow:row nowrap;padding-top:20px;padding-bottom:20px">
				<div ng-repeat="index in [].constructor(6) track by $index" ng-class="itemClass" class="bd-recommendations-item" style="flex:none;display:flex;flex-direction:column;gap:16px;">
					<div class="skeleton" style="width:100%;padding-top:100%;"></div>
					<div class="skeleton" style="width:50%;height:10px;"></div>
					<div class="skeleton" style="width:25%;height:10px;"></div>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdProductSlider', () => ({
		template,
		scope: {
			items: '=',
			useSkeleton: '=?',
			header: "@",
			rootClass: '@?',
			titleClass: '@?',
			containerClass: '@?',
			itemClass: '@?',
		},
	}))
})()
;
(function () {
	'use strict'

	const template = `
		<bd-slider-up container-class="bd-project-slider" options="sliderOptions">
			<a class="bd-project-card" ng-repeat="item in items" ng-href="{{item.href}}">
				<div class="bd-project-card__image skeleton">
					<img alt="" src="" ng-src="{{item.image}}" aria-hidden="true" />
				</div>
				<span class="font-bold">{{item.label}}</span>
			</a>
		</bd-slider-up>
	`;

	const sliderController = ['$scope', function (scope) {
		scope.sliderOptions = {
			dots: false,
			skipSnaps: true,
			slidesToScroll: 'auto',
		};
		this.items = scope.items = [];
		this.addItem = (item) => this.items.push(item);
	}];

	window.bdApp.directive('bdProjectSlider', ['$compile', '$timeout', ($compile, $timeout) => ({
		transclude: true,
		controller: sliderController,
		link(scope, element, attributes, ctrl, linker) {
			linker(scope, (copy, scope) => {
				element.append(copy);
				const slider = $compile(template)(scope);
				$timeout(() => element.replaceWith(slider));
			});
		}
	})]);

	window.bdApp.directive('bdProjectCard', [() => ({
		transclude: true,
		require: '^^bdProjectSlider',
		link(scope, elem, attr, ctrl) {
			ctrl.addItem({
				label: attr.label,
				image: attr.image,
				href: attr.href,
			});
		}
	})]);
})()
;
(function () {
	'use strict';

	let template = `
		<bd-product-slider
			header="{{header}}"
			items="items"
			use-skeleton="useSkeleton"
			root-class="bd-recommendations"
			title-class="bd-recommendations-title"
			container-class="bd-recommendations-container"
			item-class="bd-recommendations-item" />
	`;

	window.bdApp.directive('bdRecommendations', ['$timeout', 'relatedItemsServices', ($timeout, service) => ({
		template,
		scope: {
			header: "@",
			itemsNo: "=",
			useSkeleton: "=?",
			relationType: "@",
		},
		controller($scope) {
			return $scope.$watchCollection('itemsNo', (value) => {
				if (!value || value[0] === null || value.length === 0) return;
				service.getItems(value, $scope.relationType).then((result) => {
					$timeout(() => {
						$scope.$apply(() => {
							$scope.useSkeleton = false;
							$scope.items = result
						});
					});
				});
			});
		}
	})])
})()
;
(function () {
	'use strict';
	
	window.bdApp.directive('bdDisableLazy', () => ({
		controller: function ($attrs) {
			///
		}
	}));
	
	window.bdApp.directive('bdResponsiveImage', ($timeout, $filter) => ({
		replace: true,
		// require: '^^?bdDisableLazy',
		template: `<div class="bd-responsive-image-container"><bd-image alt="" src="{{imageSrc}}" width="width" height="height" loading="{{_loading}}" class="bd-responsive-image" /></div>`,
		controller: ($scope) => $scope._loading = $scope.loading ? $scope.loading : 'lazy',
		scope: {imageSrc: "@", width: "=", height: "=", loading: "="},
	}))
})()
;
(function() {
	'use strict';

	let template = `
		<div class="bd-sample-cards">
			<bd-slider plugins="['classNames','wheelGestures']">
				<ng-transclude-replace></ng-transclude-replace>
			</bd-slider>
		</div>
	`;

	window.bdApp.directive('bdSampleCards', () => ({
		template,
		replace: true,
		transclude: true,
	}));

	let templateSampleCardsItem = `
		<div ng-content-replace>
			<bd-slide>
				<bd-display on-hide="(min-width: 1920px)">
					<bd-stack class="bd-sample-cards-item" flex-direction="column" justify-content="space-between" align-items="flex-start">
						<bd-typography class="bd-sample-cards-item-title">{{title}}</bd-typography>
						<bd-typography class="bd-sample-cards-item-subtitle">{{subtitle}}</bd-typography>
						<img class="bd-sample-cards-item-image" ng-src="{{image}}" />
						<bd-button variant="link" href="{{href}}">Order Sample</bd-button>
					</bd-stack>
				</bd-display>
				<bd-display on-visible="(min-width: 1920px)">
					<bd-stack class="bd-sample-cards-item" flex-direction="column">
						<img class="bd-sample-cards-item-image" ng-src="{{image}}" />
						<bd-stack flex-direction="row" justify-content="space-between" class="bd-sample-cards-item-content">
							<bd-stack flex-direction="column">
								<bd-typography class="bd-sample-cards-item-title">{{title}}</bd-typography>
								<bd-typography class="bd-sample-cards-item-subtitle">{{subtitle}}</bd-typography>
							</bd-stack>
							<bd-button variant="link" href="{{href}}">Order Sample</bd-button>
						</bd-stack>
					</bd-stack>
				</bd-display>
			</bd-slide>
		</div>
	`;

	window.bdApp.directive('bdSampleCardsItem', () => ({
		replace: true,
		template: templateSampleCardsItem,
		scope: {href: "@", image: "@", title: "@", subtitle: "@"},
	}));
})()
;
(function () {
	'use strict'

	const template = `
		<div class="bd-selector">
			<span class="bd-selector__placeholder">
				{{selected}}
			</span>
			<ul class="bd-selector__list" ng-if="show">
				<li class="bd-selector__item" ng-repeat="option in options" ng-click="select(option)" ng-if="option.disabled !== 'true'">
					{{option.value}}
				</li>
			</ul>
		</div>
	`;

	window.bdApp.directive('bdSelector', () => ({
		template,
		replace: true,
		scope: {
			options: '<',
			ngModel: '=',
		},
		link(scope, element, attributes) {
			scope.show = false;

			scope.select = (option) => scope.ngModel = option.value;

			scope.$watch('ngModel', (value) => scope.selected = value);

			element.on('click', () => {
				scope.show = !scope.show;
				scope.$digest();
			});

			angular.element(document).on('scroll', () => {
				scope.show = false;
				scope.$digest();
			});

			angular.element(document).on('click', (event) => {
				if (element[0].contains(event.target)) return;
				scope.show = false;
				scope.$digest();
			});
		}
	}));
})()
;
(function () {
	'use strict';
	
	let template = `
		<div class="bd-share-button" ng-click="toggle($event)" title="Share">
			<svg xmlns="http://www.w3.org/2000/svg" width="17" height="24" viewBox="0 0 17 24" fill="none">
				<path d="M1.00003 12.7971V23.1337H15.4712V12.7971" stroke="black" stroke-width="1.65385" stroke-linecap="round" stroke-linejoin="round"/>
				<path d="M1.41348 7.83547L8.44233 1.63354M8.44233 1.63354L15.4712 7.83547M8.44233 1.63354V18.172" stroke="black" stroke-width="1.65385" stroke-linecap="round" stroke-linejoin="round"/>
			</svg>
			<ul ng-if="active" class="bd-share-menu" ng-jq="menu">
				<li 
					socialshare
					class="bd-share-menu-item"
					socialshare-provider="{{provider}}"
					socialshare-url="{{sharedItem.url}}"
					ng-repeat="provider in providers track by $index"
				>
					<i class="{{provider}}" />
					<span class="visually-hidden">{{provider}}</span>
				</li>
			</ul>
		</div>
	`;
	
	window.bdApp.directive('bdShareButton', () => ({
		template,
		replace: true,
		scope: { providers: '=', sharedItem: '=' },
		controller: function ($scope, $element, $timeout) {
			
			const recalculateBounds =  () => setTimeout(() => {
				let menu = $element.find('ul');
				let menuRect = menu[0].getBoundingClientRect();
				let bodyRect = document.body.getBoundingClientRect();
				
				if(bodyRect.right <= menuRect.right) menu.css('right', 0);
				else menu.css('right', '');
			}, 0);
			
			
			$scope.toggle = ($event) => {
				$event.stopPropagation();
				$scope.active = !$scope.active;
				if($scope.active) recalculateBounds();
			}
			
			angular.element(document.body).bind('click', () => {
				$scope.active = false;
				setTimeout(() => $scope.$digest(), 0);
			})
		},
	}))
})();
(function () {
	'use strict';

	let template = `
		<div class="bd-slider-up">
			<button ng-if="canScrollPrev && sliderOptions.buttons" class="bd-slider-up-btn-prev" ng-click="slider.scrollPrev()">
				<svg class="bd-embla-button-icon" viewBox="0 0 100 100">
					<path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" class="arrow"></path>
				</svg>
				<span class="visually-hidden">Prev slide</span>
			</button>
			<button ng-if="canScrollNext && sliderOptions.buttons" class="bd-slider-up-btn-next" ng-click="slider.scrollNext()">
				<svg class="bd-embla-button-icon" viewBox="0 0 100 100">
					<path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" class="arrow" transform="translate(100, 100) rotate(180)"></path>
				</svg>
				<span class="visually-hidden">Next slide</span>
			</button>
			<div class="bd-slider-up-dots" ng-class="sliderOptions.dots" ng-if="dots.length > 1 && sliderOptions.dots">
				<span class="bd-slider-up-dot" ng-class="[sliderOptions.dot, {'bd-slider-up-dot-active': selected === $index}]" ng-key="$index" ng-repeat="dot in dots"></span>
			</div>
		</div>
	`;

	window.bdApp.directive('bdSliderUp', ['$parse', '$compile', '$timeout', ($parse, $compile, $timeout) => {
		return {
			template,
			restrict: 'E',
			scope: false,
			replace: true,
			transclude: true,
			compile(element, attr, linker) {
				return (scope, element) => {
					scope.rootClass = attr.rootClass;
					scope.containerClass = attr.containerClass;
					let root = $compile('<div class="bd-slider-up-root" ng-class="rootClass"></div>')(scope);
					let container = $compile(`<div class="bd-slider-up-container" ng-class="containerClass"></div>`)(scope);
					return linker(scope, (clone, scope) => {
						element.prepend(root);
						root.append(container);
						container.append(clone);
						return $timeout((() => {
							let options = ($parse(attr.options))(scope);
							let plugins = ($parse(attr.plugins))(scope);

							scope.sliderOptions = {...options, container: container.get(0)};
							if (scope.sliderOptions.dots === undefined) scope.sliderOptions.dots = true;
							if (scope.sliderOptions.buttons === undefined) scope.sliderOptions.buttons = true;
							scope.slider = new EmblaCarousel(root.get(0), scope.sliderOptions, plugins);

							scope.slider.on('init', () => {
								$timeout(() => {
									scope.dots = scope.slider.scrollSnapList();
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});

							scope.slider.on('reInit', () => {
								$timeout(() => {
									scope.dots = scope.slider.scrollSnapList();
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});

							scope.slider.on('select', () => {
								$timeout(() => {
									scope.selected = scope.slider.selectedScrollSnap();
									scope.canScrollPrev = scope.slider.canScrollPrev();
									scope.canScrollNext = scope.slider.canScrollNext();
								}, 0);
							});
						}), 0);
					});
				}
			}
		}
	}])
})()
;
(function () {
	'use strict';
	
	var template = `
		<div class="bd-slider bd-embla" ng-class="{'bd-embla-no-animate': noAnimate}">
			<div class="bd-embla-viewport">
				<div class="bd-embla-container" ng-class="classes">
					<ng-transclude-replace></ng-transclude-replace>
				</div>
			</div>
			<div class="bd-embla-buttons" ng-if="options.showButtons">
				<button class="bd-embla-button bd-embla-button-prev">
					<svg class="bd-embla-button-icon" viewBox="0 0 100 100">
						<path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" class="arrow"></path>
					</svg>
					<span class="visually-hidden">Prev slide</span>
				</button>
				<button class="bd-embla-button bd-embla-button-next">
					<svg class="bd-embla-button-icon" viewBox="0 0 100 100">
						<path d="M 10,50 L 60,100 L 70,90 L 30,50  L 70,10 L 60,0 Z" class="arrow" transform="translate(100, 100) rotate(180)"></path>
					</svg>
					<span class="visually-hidden">Next slide</span>
				</button>
			</div>
			<div class="bd-embla-dots" ng-if="dots.length > 1 && options.dots">
				<div class="bd-embla-dot" ng-repeat="dot in dots track by $index">{{$index}}</div>
			</div>
		</div>
	`;
	
	window.bdApp.directive('bdSlider', () => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
			scope: {
				items: "=?",
				active: "=?",
				slider: "=?",
				plugins: "=?",
				options: "=?",
				emInit: "=?",
				emReinit: "=?",
				emSelect: "=?",
				noAnimate: "=?",
			},
			controller: function ($scope, $timeout, $element) {
				$scope.options = {
					watchResize: () => $scope.slides.length > 0,
					watchSlides: () => $scope.slides.length > 0,
					container: '.bd-embla-container',
					containScroll: 'trimSnaps',
					slides: '.bd-slide',
					showButtons: true,
					skipSnaps: true,
					dragFree: false,
					align: "center",
					startIndex: 0,
					dots: true,
					...$scope.options,
				};
				
				if (angular.isUndefined($scope.active)) $scope.active = true;
				
				if (!$scope.active) $scope.noAnimate = true;
				
				$scope.classes = [`bd-embla-axis-${$scope.options.axis ? $scope.options.axis : 'x'}`];
				
				let plugins = (!$scope.plugins) ? [] : [
					// EmblaCarouselClassNames(),
					// EmblaCarouselAutoHeight(),
					EmblaCarouselWheelGestures(),
					EmblaCarouselAutoplay({stopOnMouseEnter:true,stopOnInteraction:false}),
				]
					.map((plugin) => ($scope.plugins.includes(plugin.name)) ? plugin : null)
					.filter(x => x);
				
				let viewport = $element[0].querySelector('.bd-embla-viewport');
				let container = viewport.querySelector('.bd-embla-container');
				
				const scrollPrev = () => {
					if(!$scope.engine || !$scope.slider || !$scope.slider.canScrollPrev()) return;
					$scope.engine.animation.stop();
					$scope.slider.scrollPrev();
				}
				
				const scrollNext = () => {
					if(!$scope.engine || !$scope.slider || !$scope.slider.canScrollNext()) return;
					$scope.engine.animation.stop();
					$scope.slider.scrollNext();
				}
				
				const initDots = () => {
					let dots = $element[0].querySelectorAll('.bd-embla-dot');
					[].slice.call(dots).map(dot => dot.classList.remove('active'));
					if(dots[0]) dots[0].classList.add('active');
				}
				
				const initButtons = () => {
					let prevBtn = $element[0].querySelector('.bd-embla-button-prev');
					let nextBtn = $element[0].querySelector('.bd-embla-button-next');
					if(prevBtn) prevBtn.addEventListener('click', scrollPrev);
					if(nextBtn) nextBtn.addEventListener('click', scrollNext);
				}
				
				const changeButtons = () => {
					let prevBtn = $element[0].querySelector('.bd-embla-button-prev');
					let nextBtn = $element[0].querySelector('.bd-embla-button-next');
					if(prevBtn) prevBtn.style.opacity = $scope.slider.canScrollPrev() ? '1' : '0';
					if(nextBtn) nextBtn.style.opacity = $scope.slider.canScrollNext() ? '1' : '0';
				}
				
				const changeDots = () => {
					let dots = $element[0].querySelectorAll('.bd-embla-dot');
					let prevSnap = $scope.slider.previousScrollSnap();
					let selectedSnap = $scope.slider.selectedScrollSnap();
					if(dots[prevSnap]) dots[prevSnap].classList.remove('active');
					if(dots[selectedSnap]) dots[selectedSnap].classList.add('active');
				}
				
				$scope.slides = [];
				
				const initSlider = (records) => {
					if (!$scope.active) return;
					
					if (records) for (let mutation of records) {
						for (let node of mutation.addedNodes)
							if (node.classList && node.classList.contains('bd-slide')) $scope.slides.push(node);
						for (let node of mutation.removedNodes)
							if(node.classList && node.classList.contains('bd-slide')) _.remove($scope.slides, node);
					}
					
					if (!$scope.slides.length) return;
					
					setTimeout(() => {
						if($scope.slider) $scope.slider.reInit({startIndex: 0});
						else $scope.slider = new EmblaCarousel(viewport, $scope.options, plugins);
						
						$scope.engine = $scope.slider.internalEngine();
						
						$scope.dots = $scope.slider.scrollSnapList();
						
						$scope.slider.on('init', () => setTimeout(() => {
							initDots();
							initButtons();
							changeButtons();
							$element.addClass('bd-embla-active');
						}, 500));
						
						$scope.slider.on('reInit', () => setTimeout(() => {
							initDots();
							initButtons();
							changeButtons();
							$element.addClass('bd-embla-active');
						}, 500));
						
						$scope.slider.on('select', () => {
							changeDots();
							changeButtons();
						});
						
						if($scope.emInit) $scope.slider.on('init', () => $scope.emInit($scope.slider));
						if($scope.emReinit) $scope.slider.on('reInit', () => $scope.emReinit($scope.slider));
						if($scope.emSelect) $scope.slider.on('select', () => $scope.emSelect($scope.slider));
						
						$scope.$digest();
					}, 0);
				};
				
				let mutObserver = new MutationObserver((records) => initSlider(records));
				mutObserver.observe(container, {childList: true});
				
				$scope.$watch(() => $element.is(':visible'), () => $element.is(':visible') && initSlider());
			}
		}
	});
	
	var slideTemplate = `
		<div class="bd-slide bd-embla-slide">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdSlide', () => {
		return {
			scope: true,
			restrict: 'E',
			replace: true,
			transclude: true,
			require: "^^bdSlider",
			template: slideTemplate,
		}
	});
})();
(function (){
	'use strict';
	
	var template = `
		<div ng-style="style" class="bd-stack">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdStack', () => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
			scope: {
				breakpoints: "=?", // ????
				justifyContent: "@?",
				flexDirection: "@?",
				borderRadius: "@?",
				flexShrink: "@?",
				alignItems: "@?",
				height: "@?",
				width: "@?",
				flex: "@?",
				gap: "@?",
			},
			link: (scope) => {
				scope.style = {
					justifyContent: scope.justifyContent,
					flexDirection: scope.flexDirection,
					borderRadius: scope.borderRadius,
					flexShrink: scope.flexShrink,
					alignItems: scope.alignItems,
					height: scope.height,
					width: scope.width,
					flex: scope.flex,
					gap: scope.gap,
				}
			}
		}
	})
})();
(function() {
	'use strict';
	
	let template = `
		<div class="bd-tabs">
			<div class="bd-tabs-container">
				<bd-slider no-animate="true" plugins="['classNames','wheelGestures']" slider="model.slider" em-init="initSlider" options="model.sliderOptions">
					<bd-slide ng-repeat="tab in tabs track by $index">
						<label ng-if="!tab.href" class="bd-tabs-item bd-tab-item">
							<input hidden type="radio" name="bd-tab-{{model.tabId}}" ng-value="tab.index" ng-checked="model.currentIndex === tab.index" ng-change="onChanged($index)" ng-model="model.currentIndex" />
							<span>{{tab.title}}</span>
						</label>
						<a ng-if="tab.href" ng-href="{{tab.href}}" ng-class="{'bd-tab-active':tab.active}" class="bd-tabs-item bd-tab-item">
							<span>{{tab.title}}</span>
						</a>
					</bd-slide>
				</bd-slider>
			</div>
			<div class="bd-tabs-content" id="bd-tabs-content-{{model.tabId}}"></div>
		</div>
	`;
	
	window.bdApp.directive('bdTabs', () => {
		return {
			template,
			scope: true,
			replace: true,
			transclude: true,
			controller: ($scope, $timeout, $element, $transclude) => {
				if(!$transclude) return;
				
				$scope.model = {
					slider: null,
					currentIndex: 0,
					tabId: $scope.$id,
					sliderOptions: {
						dots: false,
						dragFree: true,
						showButtons: false,
					},
				};
				
				$scope.initSlider = (slider) => {
					$scope.model.currentIndex = $scope.tabs.findIndex(x => x.active);
					if($scope.model.currentIndex < 0) $scope.model.currentIndex = 0;
					slider.scrollTo($scope.model.currentIndex);
					$scope.update();
				}
				
				$scope.onChanged = (index) => {
					$scope.model.slider && $scope.model.slider.scrollTo(index)
					$scope.update();
				};
				
				$scope.update = () => {
					$element.find(`[bd-tab-content]`).removeClass('bd-tab-content-active');
					$element.find(`[bd-tab-content="${$scope.model.currentIndex}"]`).addClass('bd-tab-content-active');
				};
				
				$timeout(() => {
					$transclude((clone) => {
						let content = [].slice.call(clone).filter(x => x.nodeType !== Node.TEXT_NODE)
							.map((item, index) => (item.setAttribute && item.setAttribute('bd-tab-content', index), item));
						
						$scope.tabs = content.map((item, index) => ({
							index: index,
							href: $(item).attr('href'),
							name: $(item).attr('name'),
							title: $(item).attr('title'),
							active: $(item).attr('active'),
						}));
						
						$element.find(`#bd-tabs-content-${$scope.model.tabId}`).append(content);
					});
				})
			}
		};
	});
	
	let templateTab = `
		<div class="bd-tab-content">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdTab', () => {
		return {
			replace: true,
			transclude: true,
			template: templateTab,
		}
	})
})();
(function () {
	'use strict'
	window.bdApp.directive('bdTeleport', () => ({
		scope: false,
		transclude: true,
		compile(elem, attr, linker) {
			return (scope) => {
				return linker(scope, (copy) => {
					angular.element(attr.to).append(copy);
					elem.remove();
				})
			}
		}
	}))
})()
;
(function () {
	'use strict';
	window.bdApp.directive('bdTrustMary', ['$compile', ($compile) => ({
		link(scope, element, attributes) {
			const tag = $compile(`<script src="https://widget.trustmary.com/${attributes.key}"></script>`)(scope);
			element.replaceWith(tag);
		}
	})]);
})()
;
(function (){
	'use strict';
	
	var template = `
		<p class="bd-typography">
			<ng-transclude-replace></ng-transclude-replace>
		</p>
	`;
	
	window.bdApp.directive('bdTypography', () => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
		}
	})
})();
(function () {
	'use strict';
	
	var template = `
		<div class="bd-category-banner" ng-style="style">
			<div class="bd-category-banner-left">
				<h2 class="bd-category-banner-title" ng-transclude="bannerTitle">Banner title</h2>
				<p class="bd-category-banner-description" ng-transclude="bannerDescription">Banner description</p>
				<a class="bd-button bd-button-dark" style="margin-top: 20px" ng-href="{{ctaLink}}" ng-if="ctaLink">{{ctaText}}</a>
			</div>
			<div class="bd-category-banner-right">
				<img ng-src="{{image}}" />
			</div>
		</div>
	`;
	
	const oepCategoryBanner = (appSettings) => ({
		template,
		replace: true,
		restrict: 'E',
		scope: {
			image: "@?",
			ctaLink: "@?",
			ctaText: "@?",
			minHeight: "@?",
		},
		transclude: {
			bannerTitle: "?bannerTitle",
			bannerDescription: "?bannerDescription",
		},
		link: (scope) => {
			scope.style = {
				minHeight: scope.minHeight,
			}
		}
	});
	
	window.bdApp.directive('oepCategoryBanner', oepCategoryBanner);
})()
;
(function () {
	'use strict';
	
	var template = `
		<div class="homepage-hero-banner">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdHomepageHero', (ngDialog) => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
			controller: ($scope) => {
				$scope.disclaimer = () => {
					ngDialog.show()
				}
			}
		}
	});
	
	//
	
	var templatePicture = `
		<picture class="homepage-hero-banner-picture">
			<ng-transclude-replace></ng-transclude-replace>
		</picture>
	`;
	
	window.bdApp.directive('bdHomepageHeroPicture', () => {
		return {
			replace: true,
			restrict: 'E',
			transclude: true,
			template: templatePicture,
		}
	});
	
	//
	
	var templateContent = `
		<div class="homepage-hero-banner-wrapper">
			<ng-transclude-replace></ng-transclude-replace>
		</div>
	`;
	
	window.bdApp.directive('bdHomepageHeroContent', () => {
		return {
			replace: true,
			restrict: 'E',
			transclude: true,
			template: templateContent,
		}
	});
	
	
})();
(function() {
	'use strict';
	
	window.bdApp.directive('ngContentReplace', () => ({
		restrict: 'AE',
		link: (scope, element) => {
			let content = element.contents();
			element.replaceWith(content);
		},
	}))
})();
(function (){
	'use strict';
	
	window.bdApp.directive('ngTranscludeReplace', () => ({
		terminal: true,
		restrict: 'EA',
		scope: {slot: "@"},
		controller: function ($scope, $element, $transclude) {
			if($transclude) $transclude((clone) => {
				if(clone.length) $element.replaceWith(clone);
				else $element.remove();
			}, $scope, $scope.slot);
		}
	}))
})();
(function (){
	'use strict';
	
	var template = `
		<div class="bd-landing-header">
			<h1 class="bd-landing-header-title">{{title}}</h1>
			<p class="bd-landing-header-description">{{description}}</p>
			<picture class="bd-landing-header-image" ng-transclude></picture>
		</div>
	`;
	
	window.bdApp.directive('bdLandingHeader', () => {
		return {
			template,
			replace: true,
			restrict: 'E',
			transclude: true,
			scope: {
				title: "@",
				description: "@",
			},
		}
	})
})();
(function (){
	'use strict';
	
	var template = `
		<main class="bd-landing-page">
			<ng-transclude-replace></ng-transclude>
		</main>
	`;
	
	window.bdApp.directive('bdLandingPage', () => {
		return {
			template,
			restrict: 'E',
			replace: true,
			transclude: true,
		}
	})
})();
(function (){
	'use strict';
	
	var template = `
		<section class="bd-landing-section">
			<ng-transclude-replace></ng-transclude-replace>
		</section>
	`;
	
	window.bdApp.directive('bdLandingSection', ($window) => {
		return {
			template,
			restrict: 'E',
			replace: true,
			transclude: true,
			scope: {
				onHide: "@",
				onVisible: "@",
			},
			link: (scope, element, attributes) => {
				
				scope.windowWidth = $window.innerWidth;
				
				angular.element($window).bind('resize', () => {
					scope.windowWidth = $window.innerWidth;
					scope.$digest();
				})
				
				scope.$watch(() => scope.windowWidth, () => {
					if(!scope.onHide && !scope.onVisible) return;
					
					let mqh = $window.matchMedia(scope.onHide);
					let mqv = $window.matchMedia(scope.onVisible);
					
					var hidden = scope.onHide ? mqh.matches : !mqv.matches;
					
					attributes.$set("hidden", hidden);
				});
			}
		}
	})
})();
(function () {
	'use strict';

	let template = `
		<div class="bd-new-arrivals">
			<h1 class="bd-new-arrivals-title">New Arrivals</h1>
			<ng-transclude-replace></ng-transclude-replace>
			<bd-preloader ng-if="loading" template="preloader"></bd-preloader>
			<div ng-if="!loading && items.length <= 0">Nothing found yet</div>
			<div class="bd-new-arrivals-section" ng-if="!loading && items.length > 0" ng-repeat="item in items">
				<h2 class="bd-new-arrivals-collection-title">{{item.collection.name}}</h2>
				<p class="bd-new-arrivals-collection-description" ng-if="item.collection.description">{{item.collection.description}}</p>
				<bd-slider-up class="bd-new-arrivals-slider" options="sliderOptions" plugins="sliderPlugins">
					<div ng-if="item.collection.image" class="bd-new-arrivals-image-slide">
						<bd-image-detail width="460" height="360" image="item.collection.image"></bd-image-detail>
					</div>
					<div class="bd-new-arrivals-item-card product-card" ng-repeat="product in item.products">
						<div class="product-card-image-container skeleton">
							<a href="{{product.__href}}" target="_blank">
								<bd-image src="{{'/cdn-bedrosian/assets/products/hiresimages/' + product.imageName}}" width="250" height="250"></bd-image>
							</a>
						</div>
						<h3 class="plp-item-title"><a href="{{product.__href}}" target="_blank">{{product.name}}</a></h3>
						<div class="plp-item-info">
							<p class="plp-item-info-price">{{product.priceToDisplay.currentPrice | currency}} / {{product.sellingUom.name}}</p>
							<p class="plp-item-info-code">{{product.productCode}}</p>
							<button ng-if="product.sampleItemNo" class="plp-item-info-actions bd-button bd-button-border" ng-click="addSampleToBag(product.sampleItemNo)">Order Sample</button>
							<a href="{{product.__href}}" ng-if="!product.sampleItemNo" class="plp-item-info-actions bd-button bd-button-border">View Item</a>
						</div>
					</div>
				</bd-slider-up>
				<bd-button class="catalog-cta" style="margin-top: 20px" href="{{item.href}}" variant="dark">Shop {{item.collection.name}}</bd-button>
			</div>
		</div>
	`;

	let preloaderTemplate = `
		<div class="bd-new-arrivals-section" ng-repeat="item in [1,2,3,4,5,6]">
			<p style="width:200px"></p>
			<p style="width:250px"></p>
			<div style="display: grid; grid-auto-flow: column; grid-auto-columns: min-content">
				<div class="bd-new-arrivals-item-card product-card" ng-repeat="item in [1,2,3,4,5,6]">
					<div class="product-card-image-container skeletron-image"></div>
					<p style="width:100%;margin-top:10px;"></p>
					<p style="width:150px;min-height:15px"></p>
					<p style="width:50px;min-height:10px"></p>
				</div>
			</div>
		</div>
	`;

	window.bdApp.directive('bdNewArrivals', ($api, $parse, $requestBuilders, $addSampleDialog, appSettings) => {
		return {
			template,
			scope: true,
			replace: true,
			transclude: true,
			compile: (element, attr) => {
				return (scope) => {
					scope.preloader = preloaderTemplate;

					scope.sliderOptions = {
						align: 'end',
						skipSnaps: true,
					};

					scope.sliderPlugins = [EmblaCarouselWheelGestures()];

					let category = ($parse(attr.category))(scope) || ($parse(attr.$attr.category))(attr);

					let requestBuilder = $requestBuilders.$webproductListRequestBuilder();

					let request = requestBuilder.addCategory(category)
						.setSort('new_arrival');

					if (scope.collections.length > 0) {
						request.addFacet('ProductSeries', scope.collections.map(x => x.name));
					}

					$api.$webproduct.list(request.make()).then((res) => {
						if (!res.value) return;
						scope.items = Object.entries(
							scope.collections.reduce((group, item) => {
								group[item.name] = {
									products: res.value.products.filter(x => x.productSeries.toLowerCase() === item.name.toLowerCase()).map(item => (item.__href = appSettings.getSecureUrl(`product/detail${item.urlFriendlyStyleName ? '/' + item.urlFriendlyStyleName : ''}/?itemNo=${item.productCode}`), item)),
									href: appSettings.getSecureUrl(`product/list/?f_ProductSeries=${item.name}`, true),
									collection: item,
								}
								return group;
							}, {})
						).map(([key, value]) => value);

						// 	Object.entries(
						// 	res.value.products.reduce((group, item) => {
						// 		let collection = scope.collections.find(i => i.name === item.productSeries);
						// 		if(!collection) collection = { name: item.productSeries };
						// 		group[collection.name] = group[collection.name] ? group[collection.name] : {
						// 			href: appSettings.getSecureUrl(`product/list/?f_ProductSeries=${collection.name}`,true),
						// 			collection: collection,
						// 			products: [],
						// 		};
						// 		group[collection.name].products.push((item.__href=appSettings.getSecureUrl(`/product/detail${item.urlFriendlyStyleName ? '/' + item.urlFriendlyStyleName : ''}/?itemNo=${item.productCode}`),item));
						// 		return group;
						// 	}, {})
						// ).map((arr) => arr[1]);

						scope.items = scope.items.sort((a, b) => {
							let aIndex = scope.collections.indexOf(a.collection);
							let bIndex = scope.collections.indexOf(b.collection);
							if (aIndex < 0) aIndex = scope.items.length + 1;
							if (bIndex < 0) bIndex = scope.items.length + 1;
							return (aIndex - bIndex);
						});

						scope.loading = false;
					});
				}
			},
			controller: function ($scope) {
				$scope.loading = true;
				$scope.products = [];
				$scope.collections = [];

				$scope.addSampleToBag = (sampleNo) => $addSampleDialog.showDialog(sampleNo);

				this.addCollection = (collection) => {
					$scope.collections.push(collection);
				}

				this.addProducts = (products) => {
					$scope.products.push(...products);
				}
			},
		}
	});

	window.bdApp.directive('bdNewArrivalsItem', () => {
		return {
			replace: true,
			scope: {
				image: "@",
				products: "=",
				collection: "@",
				description: "@",
			},
			require: "^^bdNewArrivals",
			link: ($scope, $element, $attr, $ctrl) => {
				if ($scope.products) $ctrl.addProducts($scope.prodcuts);
				$ctrl.addCollection({
					image: $scope.image,
					name: $scope.collection,
					description: $scope.description,
				});
				$element.remove();
			}
		}
	});
})()
;
(function () {
	'use strict';
	
	function CustomerUsersCtrl($scope, customerUsersModel, CustomerUsersService, ngDialog, $q, appSettings, myModuleConst) {
		$scope.templates = {
			index: appSettings.getUrl(myModuleConst.customerUsersListTemplate, false),
			edit: appSettings.getUrl(myModuleConst.customerUserEditTemplate, false)
		}
		
		$scope.model = {
			roles: null,
			isBusy: false,
			isNewUser: true,
			currentUser: null,
			userForInvite: null,
			users: customerUsersModel.Users,
			readOnly: customerUsersModel.ReadOnly,
			currentTemplate: $scope.templates.index,
			identityName: customerUsersModel.IdentityName,
		};
		
		$scope.salesRoleName = myModuleConst.salesRoleName;
		
		$scope.editUser = editUser;
		$scope.blockUser = blockUser;
		$scope.inviteUser = inviteUser;
		$scope.openEditPage = openEditPage;
		$scope.cancelUserToken = cancelUserToken;
		
		function getRoles() {
			if ($scope.model.roles == null) {
				return CustomerUsersService.getRoles()
					.then(function(data) {
						$scope.model.roles = data;
					});
			} else {
				return $q.defer().resolve(true);
			}
		}
		function openEditPage(user) {
			$scope.model.isBusy = true;
			
			$q.all([getRoles(), getBranches(user)])
				.then(function() {
						// $scope.model.currentTemplate = $scope.templates.edit;
						ngDialog.open({
							scope: $scope,
							template: $scope.templates.edit,
							className: 'ngdialog-theme-plain',
							controller: 'CustomerUsersEditFormCtrl',
						})
					},
					function(data) {
						alert(data);
					})
				.then(function() {
					$scope.model.isBusy = false;
				});
		}
		
		function blockUser(user) {
			$scope.model.isBusy = true;
			CustomerUsersService.blockUser(user)
				.then(function () {
					user.IsBlocked = !user.IsBlocked;
				}, function () { })
				.then(function() {
					$scope.model.isBusy = false;
				});
		}
		
		function cancelUserToken(user) {
			ngDialog.openConfirm({
				template: '<div>' +
					'<h4>Warning.</h4></div><div class="ngdialog-message">' +
					' <p class="message">Do you want to permanently remove invitation for selected user? </p></div> ' +
					'<div class="buttons row"> ' +
					'<div class="col-xs-6">' +
					'<a class="bd_button" href="#" ng-click="confirm(confirmValue)">Yes</a> ' +
					'</div>' +
					'<div class="col-xs-6">' +
					'<a class="bd_button" href="#" ng-click="closeThisDialog()">No</a> ' +
					'</div>' +
					'</div>' +
					'</div>',
				className: 'ngdialog-theme-plain warningMessage',
				showClose: true,
				plain: 'true'
			}).then(function (success) {
					
					$scope.model.isBusy = true;
					CustomerUsersService.cancelUserToken(user)
						.then(function () {
								var index = $scope.model.users.indexOf(user);
								$scope.model.users.splice(index, 1);
								$scope.model.isBusy = false;
							},
							function () {
								$scope.model.isBusy = false;
							});
					
					deferred.resolve(true);
				},
				function (error) {
					deferred.resolve(false);
				});
		}
		
		function editUser(user) {
			$scope.model.isNewUser = false;
			setCurrentUser(user);
			openEditPage(user);
		}
		
		function inviteUser() {
			$scope.model.isNewUser = true;
			getDataForUserInvitation()
				.then(
					function() {
						setCurrentUser($scope.model.userForInvite);
						openEditPage($scope.model.userForInvite);
					},
					function(data) {
						alert(data);
					});
		}
		
		function getBranches(user) {
			if (!(user.Branches || []).length) {
				return CustomerUsersService.getBranches(user)
					.then(function(data) {
						user.Branches = data;
						$scope.model.currentUser.Branches = data;
					});
			} else {
				$scope.model.currentUser.Branches = user.Branches;
				return $q.defer().resolve(true);
			}
		}
		
		function getDataForUserInvitation() {
			if ($scope.model.userForInvite == null) {
				return CustomerUsersService.getDataForUserInvitation()
					.then(function (data) {
						$scope.model.userForInvite = data;
					});
			} else {
				var def = $q.defer();
				def.resolve(true);
				return def.promise;
			}
		};
		
		function setCurrentUser(user) {
			var idx = $scope.model.users.indexOf(user);
			if (idx == -1) {
				idx = $scope.model.users.length;
			}
			
			$scope.model.currentUser = angular.copy(user);
			$scope.model.currentUser.idx = idx;
		}
	}
	
	window.bdApp.controller('CustomerUsersCtrl', CustomerUsersCtrl).filter('unsafe', function ($sce) {
		return function (val) {
			return $sce.trustAsHtml(val);
		};
	});
})();
;
(function () {
	'use strict';
	
	function CustomerUsersEditFormCtrl($scope, $timeout, CustomerUsersService) {
		
		$scope.saveUser = saveUser;
		$scope.cancelEdit = cancelEdit;
		$scope.requireSelectBranch = requireSelectBranch;
		
		function saveUser() {
			$scope.model.isBusy = true;
			
			var action = $scope.model.currentUser.Id == 0
				? inviteUser
				: updateUser;
			
			action().then(function () {
				$scope.model.isBusy = false;
			});
		}
		
		function updateUser() {
			return CustomerUsersService.updateUser($scope.model.currentUser)
				.then(function(user) {
						$scope.model.users.splice($scope.model.currentUser.idx, 1, user);
						setJustEdited(user);
						$scope.closeThisDialog();
						// $scope.model.currentTemplate = $scope.templates.index;
					},
					function(data) {
						alert(data);
					});
		}
		
		function inviteUser() {
			return CustomerUsersService.inviteUser($scope.model.currentUser)
				.then(function (user) {
						$scope.model.users.push(user);
						setJustEdited(user);
						$scope.closeThisDialog();
						// $scope.model.currentTemplate = $scope.templates.index;
					},
					function(data) {
						alert(data);
					});
		}
		
		function cancelEdit() {
			// $scope.model.currentTemplate = $scope.templates.index;
			$scope.closeThisDialog();
		}
		
		function requireSelectBranch() {
			var selectedBranches = $scope.model.currentUser.Branches.filter(function (branch) {
				return branch.IsSelected;
			});
			
			return selectedBranches.length == 0;
		}
		
		function setJustEdited(editedUser) {
			editedUser.justEdited = true;
			$timeout(function () {
				editedUser.justEdited = false;
			}, 2000);
		}
	}
	
	window.bdApp.controller('CustomerUsersEditFormCtrl', CustomerUsersEditFormCtrl).filter('unsafe', function ($sce) {
		return function (val) {
			return $sce.trustAsHtml(val);
		};
	});
})();;
(function () {
	'use strict';

	function CustomerUsersService(appSettings, myModuleConst, $http, $window, $q) {

		return {
			getRoles: getRoles,
			getBranches: getBranches,
			inviteUser: inviteUser,
			updateUser: updateUser,
			getDataForUserInvitation: getDataForUserInvitation,
			blockUser: blockUser,
			cancelUserToken: cancelUserToken
		}

		function getRoles() {
			var def = $q.defer();

			var request = {
				url: appSettings.getUrl("CustomerUsers/GetRoles", true),
				method: 'GET',
				dataType: 'json'
			};

			$http(request)
				.success(function (response) {
					if (response.Success) {
						def.resolve(response.Value);
					} else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with Roles. Please try again or contact an administrator.");
				});

			return def.promise;
		}

		function getBranches(user) {
			var def = $q.defer();

			var request = {
				url: appSettings.getUrl("CustomerUsers/GetBranches", true),
				method: 'GET',
				dataType: 'json',
				params: { userId: user.Id }
			};

			$http(request)
				.success(function (response) {
					if (response.Success) {
						def.resolve(response.Value);
					} else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with Branches. Please try again or contact an administrator.");
				});

			return def.promise;
		}

		function getDataForUserInvitation() {
			var def = $q.defer();

			var request = {
				url: appSettings.getUrl("CustomerUsers/GetDataForUserInvitation", true),
				method: 'GET',
				dataType: 'json'
			};

			$http(request)
				.success(function (response) {
					if (response.Success) {
						def.resolve(response.Value);
					}
					else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with User for invite. Please try again or contact an administrator.");
				});

			return def.promise;
		}

		function updateUser(user) {
			var data = prepareDataForSaveUser(user);
			data.userId = user.Id;
			data.isBlocked = user.IsBlocked;

			var request = {
				url: appSettings.getUrl("CustomerUsers/SaveCustomerUser", true),
				method: 'POST',
				params: data,
				dataType: 'json'
			};

			var def = $q.defer();

			$http(request)
				.success(function (response) {
					if (response.Success) {
						if (user.Role != myModuleConst.salesRoleName) {
							user.Branches.forEach(function(branch) {
								branch.IsSelected = false;
							});
						}

						def.resolve(user);
					}
					else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with User updating. Please try again or contact an administrator.");
				});

			return def.promise;
		}

		function inviteUser(user) {
			var data = prepareDataForSaveUser(user);
			data.email = user.Email;

			var request = {
				url: appSettings.getUrl("CustomerUsers/InviteCustomerUser", true),
				method: 'POST',
				params: data,
				dataType: 'json'
			};

			var def = $q.defer();

			$http(request)
				.success(function (response) {
					if (response.Success) {
						user.Id = response.Value;
						user.IsApproved = false;
						def.resolve(user);
					} else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with User updating. Please try again or contact an administrator.");
				});

			return def.promise;
		}		

		function prepareDataForSaveUser(user) {

			var data = {
				role: user.Role
			};

			if (user.Role == myModuleConst.salesRoleName) {
				var selectedBranches = user.Branches
					.filter(function (branch) {
						return branch.IsSelected;
					})
					.map(function (branch) {
						return branch.Id;
					});

				data.branches = selectedBranches;
			};

			return data;
		}

		function blockUser(user) {
			var request = {
				url: appSettings.getUrl("CustomerUsers/BlockUser", true),
				method: 'POST',
				dataType: 'json',
				params: { userId: user.Id, isBlocked: !user.IsBlocked }
			};

			var def = $q.defer();

			$http(request)
				.success(function (response) {
					if (response.Success) {
						def.resolve(response.Value);
					} else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with Blocking of user. Please try again or contact an administrator.");
				});

			return def.promise;
		}

		function cancelUserToken(user)
		{
			var request = {
				url: appSettings.getUrl("CustomerUsers/CancelUserToken", true),
				method: 'POST',
				dataType: 'json',
				params: { customerUserMappingId: user.Id }
			};

			var def = $q.defer();

			$http(request)
				.success(function (response) {
					if (response.Success) {
						def.resolve(response.Value);
					} else {
						def.reject(response.Messages);
					}
				})
				.error(function () {
					def.reject("An error occurred with Blocking of user. Please try again or contact an administrator.");
				});

			return def.promise;
		}
	}

	angular.module('app')
		.service('CustomerUsersService', ['appSettings', 'myModuleConst', '$http', '$window', '$q', CustomerUsersService]);
})();;
(function () {
	'use strict';

	const InvoicesCtrl = ($http, $scope, $filter, $dialog, $frontend, $location, $settings, $model, $service) => {
		function getPreviousDate(days = 0) {
			let today = new Date();
			return new Date(new Date().setDate(today.getDate() - days)).toDateString();
		}

		$scope.params = {};
		$scope.request = {};
		$scope.currentPage = 0;
		$scope.filterDateVariants = [
			{
				key: 0,
				title: "Today",
				beginDate: getPreviousDate(0)
			},
			{
				key: 1,
				title: "Previous Day",
				beginDate: getPreviousDate(1)
			},
			{
				key: 2,
				title: "Last 7 days",
				beginDate: getPreviousDate(7)
			},
			{
				key: 3,
				title: "Last 14 days",
				beginDate: getPreviousDate(14)
			},
			{
				key: 4,
				title: "Last 30 days",
				beginDate: getPreviousDate(30)
			},
			{
				key: 5,
				title: "Last 60 days",
				beginDate: getPreviousDate(60)
			},
			{
				key: 6,
				title: "Last 90 days",
				beginDate: getPreviousDate(90)
			},
			{
				key: 7,
				title: "All",
				allInvoices: true
			}
		];

		$scope.service = $service;
		$scope.customer = $model.Customer;
		$scope.invoices = $model.InvoiceInfoList;
		$scope.branches = $model.CustomerBranches;
		$scope.balance = $model.CustomerBranchBalance;

		$scope.itemsPerPage = 100;
		$scope.canLoadMore = $scope.invoices.length >= $scope.itemsPerPage;
		$scope.currentPage = Math.min( Math.ceil($scope.invoices.length / $scope.itemsPerPage) - 1 );

		// fix other reason dislpay
		$scope.reasons = $model.PartialPaymentReasons;
		$scope.reasons[$scope.reasons.length - 1].Name += ' (additional comments required)';

		$scope.showPaymentDialog = (invoice) => {
			let scope = $scope.$new(false);
			scope.invoice = invoice;

			let dialog = $dialog.open({
				scope,
				showClose: false,
				controller: 'InvoicePopup',
				template: 'invoice-payment-dialog',
				className: 'ngdialog-theme-plain ngdialog-invoice-payment-dialog',
			});

			dialog.closePromise.then(() => scope.$destroy());
		}

		$scope.invoiceInfo = (invoice) => {
			let info = [];

			if (invoice.CustomerPO) info.push(`Customer PO: ${invoice.CustomerPO}`);
			if (invoice.JobName) info.push(`Job Name: ${invoice.JobName}`);

			let payment = $service.getPayment(invoice);
			if (payment) {
				let reason = $scope.reasons.find(x => x.Id === payment.PartialPaymentReason);
				if (reason) info.push(`Partial payment. ${reason.Name}. ${$filter('currency')(payment.Amount)}`);
				else info.push(`Full payment. ${$filter('currency')(payment.Amount)}`);
			}

			return info.length > 0 ? info.join('; ') : false;
		}

		$scope.proceedPayment = () => {
			let total = $service.totalPayments();

			if (total > 10000) {
				let scope = $scope.$new(true);
				scope.message = 'The maximum payment amount is $10,000.00.  Please edit your selection of invoices to proceed.'
				let dialog = $dialog.open({
					scope,
					template: 'invoices-warning-message',
					className: 'ngdialog-theme-plain warningMessage',
				});
				dialog.closePromise.then(() => scope.$destroy());
				return;
			}

			let invoices = $service.payments();

			$scope.params.busy = true;

			$http({
				method: 'POST',
				data: { invoices },
				url: $settings.getSecureUrl('Account/InvoicesPay', true),
			}).then(function (response) {
				if (response.data.success) {
					window.location.href = $settings.getSecureUrl('Checkout/Index?ShoppingBagQuoteId=' + response.data.ShoppingBagQuoteId, true);
				} else if (response.data.errors) {
					$scope.params.busy = false;
					let scope = $scope.$new(true);
					scope.message = response.data.errors.Messages[0];
					$dialog.open({
						scope,
						template: 'invoices-warning-message',
						className: 'ngdialog-theme-plain warningMessage',
					});
					$dialog.closePromise.then(() => scope.$destroy());
				}
			}, function (response) {
				window.alert(response.statusText);
				$scope.params.busy = false;
			});
		}

		$scope.loading = (last, reload = false) => {
			if (!last || !$scope.canLoadMore || $scope.params.busy) return;
			$scope.params.busy = true;
			$scope.request.itemsPerPage = $scope.itemsPerPage;
			$scope.request.page = $scope.currentPage;
			$frontend.$frontendAccount.invoices($scope.request)
				.then((result) => {
					if (!result.InvoiceInfoList) return;
					if (reload) $scope.invoices = [];
					$scope.canLoadMore = result.InvoiceInfoList.length > 0;
					$scope.invoices.push(...result.InvoiceInfoList);
				}, function (response) {
					window.alert(response.statusText);
					$scope.params.busy = false;
				}).finally(() => $scope.params.busy = false)
				.finally(() => ++$scope.currentPage);
		}

		$scope.$on('$locationChangeStart', () => {
			$scope.request = $location.search();
			$scope.params.period = $scope.filterDateVariants.find(x => x.beginDate === $scope.request.beginDate) || $scope.filterDateVariants[7];
		});

		$scope.$on('$locationChangeSuccess', (event, a, b) => {
			if (a === b) return;
			$scope.currentPage = 0;
			$scope.canLoadMore = true;
			$scope.params.search = undefined;
			$scope.loading(true, true);
		});

		$scope.$watch('params.period', (value) => {
			if (!value) return;

			if (value.allInvoices) {
				$location.search({});
				return;
			}

			$location.search({
				beginDate: value.beginDate,
				endDate: getPreviousDate(0),
			});
		});
	}

	window.bdApp.controller('InvoicesCtrl', [
		'$http',
		'$scope',
		'$filter',
		'ngDialog',
		'$frontend',
		'$location',
		'appSettings',
		'InvoiceModel',
		'InvoiceService',
		InvoicesCtrl
	]);
})();
;
(function () {
	'use strict';
	
	function InvoicePopup($scope, $service) {
		$scope.TYPE_FULL = 'full';
		$scope.TYPE_PART = 'part';
		
		$scope.payment = $service.getPayment($scope.invoice) || {
			InvoiceNo: $scope.invoice.InvoiceNo,
			Voucher: $scope.invoice.Voucher,
			Amount: $scope.invoice.Balance,
			PartialPaymentReason: null,
			Type: $scope.TYPE_FULL,
			Note: null,
		};
		
		$scope.exists = () => $service.hasPayment($scope.invoice);
		
		$scope.noteRequired = () => $scope.payment.PartialPaymentReason === 'Other';
		
		$scope.remove = () => {
			$service.removePayment($scope.payment);
			$scope.closeThisDialog();
		};
		
		$scope.apply = () => {
			if ($scope.payment.Type === $scope.TYPE_FULL) {
				$scope.payment.Note = null;
				$scope.payment.PartialPaymentReason = null;
				$scope.payment.Amount = $scope.invoice.Balance;
			}
			$scope.exists() ? $service.editPayment($scope.payment) : $service.addPayment($scope.payment)
			$scope.closeThisDialog();
		};
	}
	
	window.bdApp.controller('InvoicePopup', ['$scope', 'InvoiceService', InvoicePopup]);
})();
(function () {
	'use strict';
	
	function InvoiceService() {
		const _payments = [];
		
		const payments = () => _.cloneDeep(_payments);
		const hasPayments = () => _payments.length > 0;
		const totalPayments = () => _payments.reduce((acc, payment) => parseFloat(acc) + parseFloat(payment.Amount), 0);
		
		const addPayment = (payment) => _payments.push(payment);
		const hasPayment = (invoice) => _payments.some(x => x.InvoiceNo === invoice.InvoiceNo);
		
		const getAmount = (invoice) => {
			let payment = getPayment(invoice);
			return payment ? payment.Amount : 0;
		}
		
		const getPayment = (invoice) => {
			let payment = _payments.find(x => x.InvoiceNo === invoice.InvoiceNo)
			return _.cloneDeep(payment);
		};
		
		const editPayment = (payment) => {
			let index = _payments.findIndex(x => x.InvoiceNo === payment.InvoiceNo);
			if (~index) _payments[index] = payment;
		}
		
		const removePayment = (payment) => {
			let index = _payments.findIndex(x => x.InvoiceNo === payment.InvoiceNo);
			if (~index) _payments.splice(index, 1);
		}
		
		return {
			payments,
			hasPayments,
			totalPayments,
			getAmount,
			addPayment,
			getPayment,
			hasPayment,
			editPayment,
			removePayment,
		}
	}
	
	window.bdApp.service('InvoiceService', ['$frontend', InvoiceService])
})();;
(function () {
	'use strict';

	// Note: For now we use phone as customerId
	function notificationPreference($window, appSettings, myModuleConst, notificationPreferenceService) {
		return {
			restrict: 'E',
			scope: {
				phone: '<',
				source: '<',
				lastName: '<',
				firstName: '<',
				allowToEditPredefinedValue: '<',
			},
			templateUrl: appSettings.getUrl(myModuleConst.notificationPreferenceTemplate, false),
			link: function (scope, element, attrs) {
				scope.initialized = false;
				scope.loading = false;
				scope.subscribed = false;

				scope.init = init;
				scope.subscribe = subscribe;
				scope.unsubscribe = unsubscribe;
				scope.phoneIsValid = phoneIsValid;
				scope.model = {
					phone: scope.phone ? scope.phone.replace(/[^0-9]/g, '') : scope.phone,
					firstName: scope.firstName,
					lastName: scope.lastName,
					source: scope.source
				};

				scope.phoneIsEditable = !scope.model.phone || scope.model.phone === '' || scope.allowToEditPredefinedValue;

				function init() {
					if (!scope.model.phone || scope.model.phone === '') {
						scope.initialized = true;
					} else {
						notificationPreferenceService.checkNotificationPreference(scope.model.phone, scope.model.phone)
							.success(function (data) {
								scope.subscribed = data.value;
								scope.initialized = true;
							})
							.error(function () {
								console.log("An error occurred: notificationPreferenceService.checkNotificationPreference");
								scope.initialized = false;
							});
					}
				}

				function subscribe() {
					if (!scope.phoneIsValid())
						return;
					scope.loading = true;
					notificationPreferenceService.optIn(scope.model.phone, scope.model.phone, scope.firstName, scope.lastName, scope.source)
						.success(function (data) {
							scope.subscribed = data.success;
						})
						.error(function () {
							console.log("An error occurred: notificationPreferenceService.optIn");
						})
						.finally(function () {
							scope.loading = false;
						});
				}

				function unsubscribe() {
					if (!scope.phoneIsValid())
						return;
					scope.loading = true;
					notificationPreferenceService.optOut(scope.model.phone, scope.model.phone)
						.success(function (data) {
							scope.subscribed = !data.success;
						})
						.error(function () {
							console.log("An error occurred: notificationPreferenceService.optOut");
						})
						.finally(function () {
							scope.loading = false;
						});
				}

				function phoneIsValid() {
					return scope.model.phone && scope.model.phone.length === 10;
				}

				init();
			}
		};
	}

	angular.module('app')
		.directive('notificationPreference', ['$window', 'appSettings', 'myModuleConst', 'notificationPreferenceService', notificationPreference]);
}());
;
(function () {
	'use strict';

	function notificationPreferenceService(appSettings, $http, $q, $window, $cookies) {

		var options = {
			headers: {
				"StoreFrontPublicKey": window.StoreFrontPublicKey
			}
		};

		function checkNotificationPreference(customerId, phone) {
			var data = {
				customer: customerId,
				phone: phone
			};
			return $http.post($window.WebApiBaseUrl + 'notificationpreference/CheckNotificationPreference', data, options);
		}

		function optIn(customerId, phone, firstName, lastName, source) {
			var data = {
				customer: customerId,
				phone: phone,
				firstName: firstName,
				lastName: lastName,
				source: source
			};
			return $http.post($window.WebApiBaseUrl + 'notificationpreference/OptInCustomerSmsNotification', data, options);
		}

		function optOut(customerId, phone) {
			var data = {
				customer: customerId,
				phone: phone
			};
			return $http.post($window.WebApiBaseUrl + 'notificationpreference/OptOutCustomerSmsNotification', data, options);
		}

		return {
			checkNotificationPreference: checkNotificationPreference,
			optIn: optIn,
			optOut: optOut
		}
	}
	angular.module('app')
		.service('notificationPreferenceService', ['appSettings', '$http', '$q', '$window', '$cookies', notificationPreferenceService]);
}());
;
(function () {
	'use strict';
	
	function OrdersCtrl($scope, ordersList, branchesList, OrdersService, $filter) {
		
		//This is jsut for test. http://gitlab.bedrosians.com/Bedrosians/oep/issues/1898 is in progress.
		//Order.aspx and RetailOrders.aspx
		
		$scope.init = function (mode) {
			if (mode === 'retail') {
				$scope.retrieveOrders = OrdersService.GetRetailOrders;
			} else {
				$scope.retrieveOrders = OrdersService.GetOrders;
			}
		};
		
		$scope.branchesList = branchesList;
		$scope.branchName = branchesList[0].Text;
		
		$scope.currentPage = 0;
		
		$scope.statusList = [
			{ Code: "All", Name: "All" },
			{ Code: "Open", Name: "Open" },
			{ Code: "Completed", Name: "Completed" },
		];
		
		$scope.datesRangeList = [
			{ Value: 14, Name: "Last 14 days" },
			{ Value: 30, Name: "Last 30 days" },
			{ Value: 60, Name: "Last 60 days" },
			{ Value: 120, Name: "Last 3 months" },
			{ Value: 240, Name: "Last 6 months" },
			{ Value: 365, Name: "Last 1 year" },
		];
		
		$scope.itemsPerPageList = [
			{ Value: 20, Name: "Per page: 20" },
			{ Value: 50, Name: "Per page: 50" },
			{ Value: 100, Name: "Per page: 100" },
			{ Value: 200, Name: "Per page: 200" },
		];
		
		$scope.orders = ordersList;
		
		$scope.model = {
			branch: {},
			search: "",
			loadingOrders: false,
			status: $scope.statusList[1],
			datesRange: $scope.datesRangeList[0],
			itemsPerPage: $scope.itemsPerPageList[0],
		};
		
		$scope.model.branch = $.grep($scope.branchesList, function (n) {
			return n.IsActive === true;
		})[0];
		
		$scope.GetOrders = function () {
			
			var params = {
				q: $scope.model.search || null,
				page: $scope.currentPage || null,
				status: $scope.model.status.Code || null,
				branch: $scope.model.branch.Value || null,
				itemsPerPage: $scope.model.itemsPerPage.Value || null,
				datesRange: $scope.model.datesRange.Value || null,
			};
			
			$scope.orders = [];
			$scope.model.loadingOrders = true;
			
			$scope.retrieveOrders(params).then(function (result) {
				$scope.orders = result;
				
				$scope.model.loadingOrders = false;
				
				$scope.togglePage = false;
				$scope.toggleStatus = false;
				$scope.toggleDisplay = false;
				
			}, function (error) {
				console.log(error);
				$scope.model.loadingOrders = false;
			});
		};
		
		//pagination
		$scope.prevPage = function () {
			if ($scope.currentPage > 0) {
				$scope.currentPage--;
			}
			$scope.GetOrders();
		};
		
		$scope.prevPageDisabled = function () {
			return $scope.currentPage === 0 ? "disabled" : "";
		};
		
		$scope.nextPage = function () {
			$scope.currentPage++;
			$scope.GetOrders();
		};
		
		$scope.nextPageDisabled = function () {
			return $scope.model.itemsPerPage.Value > $scope.orders.length ? "disabled" : "";
		};
		
		$scope.applyFilter = function () {
			$scope.currentPage = 0;
			$scope.GetOrders();
		};
		
		$scope.setBranch = function () {
			$scope.currentPage = 0;
			$scope.GetOrders();
		};
	}

	window.bdApp.controller('OrdersCtrl', ['$scope', 'ordersList', 'branchesList', 'OrdersService', '$filter', OrdersCtrl]);

	window.bdApp.filter('offset', function () {
		return function (input, start) {
			start = parseInt(start, 10);
			return input.slice(start);
		};
	});
})();
;
(function () {
	'use strict';

	function OrdersService(appSettings, $http, $q) {

		var retrieveOrders = function (url) {
			return function (params) {
				var def = $q.defer();
				$http({
					url: appSettings.getUrl(url, true),
					method: 'GET',
					params: params,
					dataType: 'json'
				}).success(function (data) {
					if (data) {
						def.resolve(data.Orders);
					} else {
						def.reject("Failed to get orders!");
					}
				})
					.error(function () {
						def.reject(
							"An error occurred while sending your enquiry. Please try again or contact an administrator.");
					});
				return def.promise;
			};
		};

		var getOrders = retrieveOrders("Account/Orders");
		var getRetailOrders = retrieveOrders("Account/RetailOrders");

		return {
			GetOrders: getOrders,
			GetRetailOrders: getRetailOrders
		};
	}

	angular.module('app')
			.service('OrdersService', ['appSettings', '$http', '$q', OrdersService]);
})();
;
(function () {
	"use strict";

	function ProductDetailCtrl(
		$api,
		$scope,
		spinner,
		ngDialog,
		appUtils,
		$location,
		$frontend,
		appSettings,
		$bannerService,
		$addSampleDialog,
		productDetailModel,
		$shoppingbagService,
		UomConversionService,
		recentProductsService,
		$productOptionsService,
		googleTagManagerService,
	) {
		$scope.docs = [];
		$scope.otherDocs = [];

		$scope.firstLoad = false;

		$scope.data = {
			unit: 0,
			overage: 0,
			needed: null,
			itemMode: null,
			totalAmount: null,
			fulfillment: null,
			availability: null,
			totalSellQty: null,
			totalHandlingQty: null,
			fulfillmentOptions: [
				{
					id: 1,
					label: "Shipping",
					value: "Shipping",
				},
				{
					id: 2,
					label: "In Store Pickup",
					value: "Will Call / Pickup",
				}
			],
		};

		$scope.applications = [
			{
				code: "F",
				name: "Floors",
			},
			{
				code: "W",
				name: "Walls",
			},
			{
				code: "C",
				name: "Countertops",
			},
			{
				code: "SW",
				name: "Shower Walls",
			},
			{
				code: "SP",
				name: "Showers Floors",
			},
			{
				code: "P",
				name: "Pools",
			}
		];

		$scope.optionsTemplate = null;
		$scope.calculatorTemplate = null;

		$scope.model = null;
		$scope.sample = null;
		$scope.currentItem = productDetailModel;

		$scope.AS_AVAILABLE = 'AVAILABLE';
		$scope.AS_OUTOFSTOCK = 'OUTOFSTOCK';
		$scope.AS_BACKORDERED = 'BACKORDERED';

		$scope.CT_SLAB = 'slab';
		$scope.CT_TOOLS = 'tools';
		$scope.CT_DEFAULT = 'default';

		$scope.IM_FULL = 'full';
		$scope.IM_SAMPLE = 'sample';

		function addItemToRecent() {
			recentProductsService.AddOrUpdateRecent({
				href: $location.absUrl(),
				name: $scope.currentItem.Product.Name,
				imageName: $scope.currentItem.Product.ImageName,
				sellingUom: $scope.currentItem.Product.SellingUom,
				priceToDisplay: $scope.currentItem.Product.PriceToDisplay,
				Updated: new Date().toUTCString(),
				ProductCode: $scope.currentItem.Product.ProductCode,
			});
		}

		async function loadSample() {
			if (!$scope.busy) $scope.busy = true;
			return $scope.sample = await $frontend.$product.detail($scope.currentItem.Product.SampleItemNo);
		}

		async function reloadModel() {
			$scope.isSellableOnline = $scope.model.Product.IsSellableOnline;
			$scope.minOrderQty = $scope.model.Product.MinOrderQty;
			await calculateTotalAmount();
		}

		function replaceImageUrl(image) {
			return {
				zoomUrl: image.replace(/(upload).*(v1)/g, `upload/t_zoom,f_auto/v1`),
				thumbUrl: image.replace(/(upload).*(v1)/g, `upload/t_product_150,f_auto/v1`),
				imageUrl: image.replace(/(upload).*(v1)/g, `upload/t_product_detail,f_auto/v1`),
			}
		}

		function calculateTotalSellQty() {
			$scope.data.unit = UomConversionService.adjustSellQtyToSolidBaseUnitQty(
				$scope.data.needed,
				$scope.model.Product.SellingUom
			);

			$scope.data.sellingPerHandlingQty = UomConversionService.calculateSellingPerHandlingQty(
				$scope.model.Product.SellingUom,
				$scope.model.Product.HandlingUom
			);

			$scope.data.totalHandlingQty = (() => {
				let overage = appUtils.round($scope.data.unit * ($scope.data.overage / 100), 4);
				let total = appUtils.round($scope.data.unit + overage, 4);
				return UomConversionService.calculateTotalHandlingQty(total, $scope.model.Product.SellingUom, $scope.model.Product.HandlingUom);
			})();

			return ($scope.sameUom()) ? (() => {
				let overage = appUtils.round($scope.data.unit * ($scope.data.overage / 100), 4);
				let total = appUtils.round($scope.data.unit + overage, 4);
				return $scope.model.Product.SellingUom.IsFractional ? total : Math.ceil(total);
			})() : appUtils.round($scope.data.totalHandlingQty * $scope.data.sellingPerHandlingQty, 4);
		}

		async function loadProductInfo() {
			return await $frontend.$product.detail($scope.itemNo);
		}

		async function loadTearsheetUrl() {
			let res = await $frontend.$product.getTearsheet($scope.currentItem.Product.ProductSeries);
			return res.Value ? `http://cdn.bedrosians.com/assets/products/pdfs/${res.Value.ProductCode}.pdf` : null;
		}

		async function loadProductIcons() {
			let icons = $scope.getProperty("DescriptionIcons");
			return Promise.resolve(icons ? icons.split(",") : []);
		}

		async function loadProductImages() {
			let mainImage = makeProductImage($scope.currentItem.Product.ImageName);
			let images = await $frontend.$product.getAssociatedProductImages($scope.itemNo, 30);
			return [mainImage, ...images.value.map(image => replaceImageUrl(image))];
		}

		async function loadProductOptions() {
			return await $productOptionsService.init($scope.currentItem);
		}

		function makeProductImage(imageName) {
			return {
				zoomUrl: `https://res.cloudinary.com/bedrosians/image/upload/t_zoom,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/${imageName}`,
				thumbUrl: `https://res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/${imageName}`,
				imageUrl: `https://res.cloudinary.com/bedrosians/image/upload/t_product_detail,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/${imageName}`,
			}
		}

		async function loadCollectionImages() {
			let data = {
				pageSize: 50,
				pageIndex: 1,
				facets: [{
					key: "Tags",
					values: [
						`collection_${$scope.currentItem.Product.ProductSeries
							.replace(/[^a-z0-9_]+/gi, '-').replace(/^-|-$/g, '').toLowerCase()}`
					]
				}]
			};

			let images = await $api.$gallery.list(data);

			return images.value.images.sort((a, b) => a.id > b.id ? 1 : -1)
				.map(image => (image.src = image.src.replace(/(upload).*(v1)/g, `upload/t_product_detail,f_auto/v1`), image));
		}

		async function calculateTotalAmount() {
			if (!$scope.data.needed && ($scope.isMoq || $scope.data.itemMode === $scope.IM_SAMPLE))
				$scope.data.needed = $scope.isMoq ? $scope.minOrderQty : 1;

			if (!$scope.data.needed) return;

			try {
				$scope.busy = true;
				$scope.data.totalSellQty = calculateTotalSellQty();
				$scope.data.availability = await loadProductAvailability($scope.data.totalSellQty);
				$scope.data.totalAmount = appUtils.round($scope.data.totalSellQty * $scope.data.availability.price.currentPrice);
				if ($scope.data.availability.options.length === 1) $scope.data.fulfillment = $scope.data.availability.options[0].type;
			} catch (error) {
				console.error(error);
			} finally {
				$scope.busy = false;
				$scope.$digest();
			}
		}

		function convertImageToGalleryDetail(image) {
			return {
				...image,
				src: image.largeImageSrc,
			};
		}

		async function loadProductAvailability(unit = 1) {
			let result = await $frontend.$product.availability($scope.model.Product.ProductCode, unit);
			let isAvailable = result.value.price && result.value.options.some(option => option.leadTime >= 0);
			result.value.options = result.value.options.map(i => (i.optionAvailable = !!(i.leadTime >= 0 || i.eta), i));
			return {
				...result.value,
				status: isAvailable ? $scope.AS_AVAILABLE : result.value.options[0].eta ? $scope.AS_BACKORDERED : $scope.AS_OUTOFSTOCK
			};
		}

		$scope.sameUom = function () {
			if (!$scope.model) return false;
			if (!$scope.model.Product.HandlingUom || !$scope.model.Product.SellingUom) return true;
			return $scope.model.Product.HandlingUom.Id === $scope.model.Product.SellingUom.Id;
		}

		$scope.$$isTool = function () {
			return $scope.currentItem.Product.MaterialCategory.toLowerCase().includes('tools');
		}

		$scope.$$isSlab = function () {
			return $scope.currentItem.Product.MaterialCategory.toLowerCase().includes('slab');
		}

		$scope.emailToOrder = function () {
			return (
				"mailto:onlineorders@bedrosians.com?subject=Order:%20" +
				$scope.model.Product.ProductCode +
				"&body=" +
				encodeURIComponent(
					"I am interested in the following product:\n\nItem Code:"
				) +
				$scope.model.Product.ProductCode +
				encodeURIComponent("\nCustomer Type ") +
				"%28Homeowner%2C%20Architect%2FDesigner%2C%20Dealer%2C%20Contractor%2FFabricator%2C%20Builder%2FProperty%20Manager%29%3A" +
				encodeURIComponent("\nJob Name:\nQuantity: ") +
				$scope.data.unit +
				"%20" +
				$scope.model.Product.SellingUom.Id +
				encodeURIComponent("\n\t") +
				"%28Enter%20%27Sample%27%20to%20order%20a%20sample%29" +
				encodeURIComponent(
					"\nStore Location: " +
					$scope.model.SelectedBranch.locationcode +
					"-" +
					$scope.model.SelectedBranch.city +
					"," +
					$scope.model.SelectedBranch.state
				) +
				encodeURIComponent("\nShip to/Pick-Up Address: ") +
				encodeURIComponent("\nCustomer Name: ")
			);
		}

		$scope.hasProperty = function (prop) {
			return $scope.currentItem.Properties.some(x => x.Key === prop);
		}

		$scope.getProperty = function (prop) {
			if ($scope.hasProperty(prop) === false) return false;
			return ($scope.currentItem.Properties.find(x => x.Key === prop)).Value;
		}

		$scope.$$calculatorType = function () {
			return $scope.$$isTool() ? $scope.CT_TOOLS : $scope.$$isSlab() ? $scope.CT_SLAB : $scope.CT_DEFAULT;
		}

		$scope.addToBag = async function (form) {
			if (form.$invalid) return;

			let selectedOption = $scope.data.availability.options.find(function (x) {
				return x.type === $scope.data.fulfillment;
			});

			if (!selectedOption) {
				alert("Please select Delivery or Pickup");
				return;
			}

			$scope.busy = true;

			let data = {
				qty: $scope.data.totalSellQty,
				storeCode: selectedOption.branchNo,
				itemNo: $scope.model.Product.ProductCode,
			};

			let item = {
				name: $scope.model.Product.Name,
				totalAmount: $scope.data.totalAmount,
				currency: $scope.model.Price.Currency,
				totalSellQty: $scope.data.totalSellQty,
				imageName: $scope.model.Product.ImageName,
				productCode: $scope.model.Product.ProductCode,
				currentPrice: $scope.model.Price.CurrentPrice,
				totalHandlingQty: $scope.data.totalHandlingQty,
				sellingUom: $scope.model.Product.SellingUom.Name,
				handlingUom: $scope.model.Product.HandlingUom.Name,
				isSample: $scope.data.itemMode === $scope.IM_SAMPLE,
			};

			await $shoppingbagService.addItemToBag(item, data);

			$scope.busy = false;

			setTimeout(() => $scope.$digest(), 0);
		}

		$scope.changeItemMode = async function () {
			try {
				if (!$scope.currentItem.Product.SampleItemNo) $scope.data.itemMode = $scope.IM_FULL;

				$scope.model = ($scope.data.itemMode === $scope.IM_FULL) ? $scope.currentItem
					: $scope.sample && $scope.sample.Product && $scope.currentItem.Product.SampleItemNo === $scope.sample.Product.ProductCode
						? $scope.sample : await loadSample();

				if ($scope.data.itemMode === $scope.IM_SAMPLE && !$scope.sample.Product) {
					$scope.data.itemMode = $scope.IM_FULL;
					$scope.model = $scope.currentItem;
					alert('Sample not available');
				}

				$scope.data.needed =
					$scope.data.totalAmount =
						$scope.data.availability =
							$scope.data.totalHandlingQty = null;

				if ($scope.data.itemMode === $scope.IM_SAMPLE) {
					$scope.notReloadItem = true;
					$location.search('sample', 'true');
					$location.state(JSON.parse(JSON.stringify($scope.currentState)));
				} else {
					$scope.notReloadItem = true;
					$location.search('sample', null);
					$location.state(JSON.parse(JSON.stringify($scope.currentState)));
				}

				if ($scope.prevNo === $scope.model.Product.ProductCode) return;

				await reloadModel();

				let moqPrice = ($scope.model.MoqPrice) ? $scope.model.MoqPrice.CurrentPrice : (($scope.model.MoqPriceHidden) ? $scope.model.MoqPriceHidden.CurrentPrice : 0);

				const image = makeProductImage($scope.model.Product.ImageName);

				googleTagManagerService.ItemOpened({
					eta: $scope.model.Product.Eta,
					productImageUrl: image.imageUrl,
					productUrl: window.location.href,
					productName: $scope.model.Product.Name,
					productSku: $scope.model.Product.ProductCode,
					availability: $scope.model.Product.IsInStock,
					productSeries: $scope.model.Product.ProductSeries,
					productDescription: $scope.model.Product.Description,
				}, moqPrice);

				googleTagManagerService.ViewItemEvent(
					$scope.model.Product.ProductCode,
					moqPrice,
					$scope.model.Product.Name,
					$scope.model.Product.Description,
					($scope.model.__meta__) ? $scope.model.__meta__.headers('Tags_EventId') : null,
				);

				googleTagManagerService.ViewItemCommerce({
					qty: 1,
					needed: 1,
					name: $scope.model.Product.Name,
					currency: $scope.model.Price ? $scope.model.Price.Currency : null,
					price: $scope.model.Price ? $scope.model.Price.CurrentPrice : 0,
					code: $scope.model.Product.ProductCode,
					color: $scope.model.Product.SeriesColor,
					category1: $scope.model.Product.Category1,
					category2: $scope.model.Product.Category2,
					category3: $scope.model.Product.Category3,
					category4: $scope.model.Product.Category4,
					isInStock: $scope.model.Product.IsInStock,
					uom: $scope.model.Product.SellingUom.Name,
					discount: $scope.model.Price ? $scope.model.Price.MsrpPrice - $scope.model.Price.CurrentPrice : 0,
				}, ($scope.model.__meta__) ? $scope.model.__meta__.headers('Tags_EventId') : null,);

				if ($scope.firstLoad) googleTagManagerService.AddPageSchema({
					"@context": "http://schema.org",
					"@type": "Product",
					"image": image.imageUrl,
					"name": $scope.model.Product.Name,
					"sku": $scope.model.Product.ProductCode,
					"description": $scope.model.Product.Description,
					"offers": {
						"@type": "Offer",
						"price": moqPrice,
						"priceCurrency": "USD",
						"availability": $scope.model.Product.IsInStock
							? "https://schema.org/InStock" : "https://schema.org/BackOrder"
					}
				})

				$scope.prevNo = $scope.model.Product.ProductCode;

				$scope.firstLoad = true;
			} finally {
				$scope.busy = false;
				setTimeout(() => $scope.$digest(), 0);
			}
		}

		$scope.hasExterior = function (prop, code) {
			if (code === 'F' || code === 'SP') return false;
			let values = $scope.getProperty(prop);
			return values && values.split(',').includes('X' + code);
		}

		$scope.hasCrossSymbol = function (prop, code) {
			if (code !== 'F' && code !== 'SP') return false;
			let values = $scope.getProperty(prop);
			return values && values.split(',').includes('X' + code);
		}

		$scope.hasApplication = function (prop, code) {
			let values = $scope.getProperty(prop);
			return values && values.split(',').includes(code);
		}

		$scope.handleOverageChange = async function () {
			await calculateTotalAmount();
		}

		$scope.featureClicked = function (feature, detail) {
			googleTagManagerService.SiteFeatureEvent(feature, detail);
		}

		$scope.handleQtyChange = async function (form, event) {
			$scope.data.overage = 0;
			$scope.data.needed = null;
			$scope.data.totalAmount = 0;
			$scope.data.availability = null;

			if (form.qty.$invalid) return;

			event.target.blur();

			let roundedHandlingQty = Math.ceil($scope.data.totalHandlingQty);

			let sellingPerHandlingQty = UomConversionService.calculateSellingPerHandlingQty(
				$scope.model.Product.SellingUom,
				$scope.model.Product.HandlingUom
			);

			$scope.data.needed = appUtils.round(sellingPerHandlingQty * roundedHandlingQty, 2);

			await calculateTotalAmount();

			if (form.needed) form.needed.$setTouched();
		}

		$scope.handleNeededChange = async function (form, event) {
			$scope.data.overage = 0;
			$scope.data.totalAmount = 0;
			$scope.data.availability = null;
			$scope.data.totalHandlingQty = null;

			if (form.needed.$invalid) return;

			event.target.blur();

			$scope.data.needed = $scope.isMoq && $scope.data.needed < $scope.minOrderQty
				? $scope.minOrderQty : $scope.data.needed;

			await calculateTotalAmount()

			if (form.qty) form.qty.$setTouched();
		}

		$scope.showCollectionImageDetail = function (image) {
			let scope = $scope.$new();

			scope.images = $scope.gallery;
			scope.currentId = image.id;
			scope.noReplace = true;

			ngDialog.open({
				scope,
				controller: 'GalleryDetailController',
				className: "ngdialog-theme-plain ngdialog-gallery-detail",
				template: appSettings.getUrl("scripts/app-spa/gallery/galleryDetail.template.html"),
			});
		}

		$scope.$on('$locationChangeSuccess', async (event, newUrl, oldUrl, newState, oldState) => {
			if ($scope.notReloadItem) {
				$scope.notReloadItem = false;
				if (newState && oldState && newState.ProductCode === oldState.ProductCode) return;
			}

			$scope.currentState = newState;

			try {
				$scope.busy = true;

				if (newState !== oldState) $scope.currentItem = await loadProductInfo();
				if (!$scope.$$isTool()) $scope.options = await loadProductOptions();

				if ($scope.currentItem.Resources.length > 0) {
					let warnings = $scope.currentItem.Resources.filter((item) => item.Key.toLowerCase().includes('product warning'))[0];
					let instructions = $scope.currentItem.Resources.filter((item) => item.Key.toLowerCase().includes('product use instruction'))[0];
					let sds = $scope.currentItem.Resources.filter((item) => item.Key.toLowerCase().includes('safety data sheet'))[0];
					let docParts = [
						{resource: warnings, title: "Product Warning"},
						{resource: instructions, title: "Product Use Instruction"},
						{resource: sds, title: "Safety Data Sheet"}
					].filter((item) => item.resource);

					$scope.docs = docParts.map(x => x.resource);
					$scope.otherDocs = $scope.currentItem.Resources.filter((item) => !$scope.docs.some(x => x.Key === item.Key));

					let docTitleParts = docParts.map(x => x.title);
					if (docTitleParts.length >= 2) {
						$scope.docsTitle = docTitleParts.slice(0, -1).join(', ') + ' and ' + docTitleParts[docTitleParts.length - 1];
					} else {
						$scope.docsTitle = docTitleParts.join(', ');
					}
				}

				await $scope.changeItemMode();

				$scope.calculatorType = $scope.$$calculatorType();
				$scope.optionsTemplate = `pdp-options-${$scope.calculatorType}`;
				$scope.calculatorTemplate = `pdp-calculator-${$scope.calculatorType}`;
			} catch (error) {
				console.error(error);
			} finally {
				$scope.loaded = true;
				$scope.busy = false;
				setTimeout(() => $scope.$digest(), 0);
			}

			try {
				$scope.images = await loadProductImages();

				$scope.tearsheetUrl = await loadTearsheetUrl();

				$scope.icons = await loadProductIcons();

				if (!$scope.gallery) $scope.gallery = await loadCollectionImages();

				await $bannerService.reload();

				// $scope.recentItems = recentProductsService.GetRecentItemsByKey();

				addItemToRecent();
			} catch (error) {
				console.error(error);
			} finally {
				setTimeout(() => $scope.$digest(), 0);
			}
		});

		$scope.$on('$locationChangeStart', (event, newUrl, oldUrl, newState, oldState) => {
			if ($scope.notReloadItem && newState && oldState && newState.ProductCode === oldState.ProductCode) return event.preventDefault();

			let search = $location.search();

			$scope.queryId = search.queryId;
			$scope.itemNo = search.itemNo;
			$scope.isMoq = search.moq;

			$scope.data.itemMode = search.sample ? $scope.IM_SAMPLE : $scope.IM_FULL;

			if (newState && newState.ImageName) $scope.images = [makeProductImage(newState.ImageName)];

			document.title = $scope.currentItem.Product.Name;

			setTimeout(() => $scope.$digest(), 0);
		});
	}

	window.bdApp.controller("ProductDetailCtrl", ProductDetailCtrl).config(['$locationProvider', ($locationProvider) => {
		$locationProvider.html5Mode({
			enabled: true,
			requireBase: false,
			rewriteLinks: false,
		})
	}]);
})();
;
(function () {
	'use strict';

	function ProductListController($scope, $location) {
		const check = (filters, reload) => {
			let search = $location.search();
			for (let key in search) key.includes('f_') && delete search[key];
			$location.search({...search, ...filters});
			$location.state(reload);
		}

		$scope.productClicked = function (productCode) {
			$scope.$gtm.ItemViewedEvent(productCode, true);
			return true;
		};

		$scope.$filter.setRefinements($scope.$model.refinements);

		$scope.$filter.onChanged((filters) => {
			$scope.$emit('oep.filter.busy');
			check(filters, true);
		});

		$scope.removeSearchFilter = () => {
			$scope.$emit('oep.filter.busy');
			let search = $location.search();
			delete search['criteria'];
			$location.search(search);
			$location.state(true);
		}

		$scope.$on('$locationChangeSuccess', (e, a, b, c) => c && window.location.reload());

		$scope.$emit('oep.filter.ready');

		// remove unselected filter
		let filters = $scope.$filter.getFilters();
		check(filters, false);

		$scope.$filter.init(true);
	}

	window.bdApp.run(['$serviceInjector', (injector) => injector.inject({
		'$gtm': 'googleTagManagerService',
		'$quickAdd': 'QuickAddService',
		'$filter': 'oepFilterService',
		'$navinfo': '$navinfo',
		'$model': '$model',
	})]);

	window.bdApp.controller('ProductListController', ['$scope', '$location', ProductListController]);
})();
;
(function () {
	'use strict'

	const template = `
		<div class="ngdialog-quick-add-container progress-enabled" ng-class="{'busy':data.busy}">
			<a target="_blank" ng-href="{{item.href}}">
				<img alt="" aria-hidden="true" class="ngdialog-quick-add-image" ng-src="https://res.cloudinary.com/bedrosians/image/upload/t_product_500,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/{{current.Product.ImageName}}" />
			</a>
			<form name="addToBagForm" ng-submit="addToBag(addToBagForm)" class="ngdialog-quick-add-content" novalidate>
				<div class="ngdialog-quick-add-content-header">
					<div ng-if="current.Product.UrlFriendlyTags[0]" class="bd-product-tag bd-product-tag--{{current.Product.UrlFriendlyTags[0]}}">
						{{current.Product.Tags[0]}}
					</div>
					<p class="ngdialog-quick-add-subtitle">{{current.Product.ProductCode}}</p>
					<a target="_blank" ng-href="{{item.href}}" class="ngdialog-quick-add-title">{{current.Product.Name}}</a>
					<p class="ngdialog-quick-add-text" ng-if="current.Price && current.Product.WebPriceMode != 1">
						<span class="plp-product-price">{{current.Price.CurrentPrice | currency}} / {{current.Product.SellingUom.Name}}</span>
					</p>
					<p class="pdp-page-product-pricing" ng-if="current.Price && current.Product.WebPriceMode == 1">
						<span class="plp-product-price">Add to cart for price</span>
					</p>
				</div>
				<div class="ngdialog-quick-add-content-body" ng-if="item.Product">
					<p class="ngdialog-quick-add-text">How much do you need?</p>
					<div class="ngdialog-quick-add-actions gap-2" ng-if="item.Product.SampleItemNo">
						<div class="w-full text-center label-switcher">
							<input id="IM_FULL" hidden="hidden" type="radio" name="sample-mode" ng-model="data.mode" ng-value="IM_FULL" ng-checked="data.mode === IM_FULL" />
							<label for="IM_FULL">Full Size</label>
						</div>
						<div class="w-full text-center label-switcher">
							<input id="IM_SAMPLE" hidden="hidden" type="radio" name="sample-mode" ng-model="data.mode" ng-value="IM_SAMPLE" ng-checked="data.mode === IM_SAMPLE" />
							<label for="IM_SAMPLE">Sample</label>
						</div>
					</div>
					<div class="form-group pdp-page-inputs">
						<div class="form-group" ng-if="!sameUom()">
							<div class="input-group" ng-class="{'ng-error': addToBagForm.needed.$invalid, 'ng-untouched': addToBagForm.needed.$untouched}">
								<input
									required
									id="needed"
									type="text"
									name="needed"
									maxlength="9"
									autocomplete="off"
									inputmode="numeric"
									class="form-control"
									ng-model="data.needed"
									ng-value="data.needed"
									ng-focus="event=$event"
									placeholder="Enter quantity"
									ng-model-options="{debounce: 500}"
									ng-pattern="/(?=.+)(?:[1-9]\\d*|0)?(?:\\.\\d+)?/"
									ng-change="handleNeededChange(addToBagForm, event)" />
								<label for="needed" id="needed-label" class="input-group-addon">
									{{current.Product.SellingUom.Name ? current.Product.SellingUom.Name.replace("\\(s\\)",'').toLowerCase() : 'quantity'}}
								</label>
							</div>
							<span ng-if="addToBagForm.needed.$error.required && addToBagForm.needed.$touched" class="help-block">This field is required.</span>
							<span ng-if="addToBagForm.needed.$error.pattern && addToBagForm.needed.$touched" class="help-block">This field can only contain positive numbers.</span>
						</div>
						<span class="pdp-page-inputs-divider" ng-if="!sameUom()">or</span>
						<div class="form-group">
							<div class="input-group" ng-class="{'ng-error': addToBagForm.qty.$invalid, 'ng-untouched': addToBagForm.qty.$untouched}">
								<input
									required
									id="qty"
									name="qty"
									type="text"
									tabindex="-1"
									maxlength="9"
									autocomplete="off"
									inputmode="numeric"
									class="form-control"
									ng-focus="event=$event"
									ng-pattern="/[1-9]\\d*/"
									placeholder="Enter quantity"
									ng-value="data.totalHandlingQty"
									ng-model="data.totalHandlingQty"
									ng-model-options="{debounce: 500}"
									ng-change="handleQtyChange(addToBagForm, event)" />
								<label for="qty" id="qty-label" class="input-group-addon">
									{{current.Product.HandlingUom.Name ? current.Product.HandlingUom.Name.replace("\\(s\\)",'').toLowerCase() : 'quantity'}}
								</label>
							</div>
							<span ng-if="addToBagForm.qty.$error.required && addToBagForm.qty.$touched" class="help-block">This field is required.</span>
							<span ng-if="addToBagForm.qty.$error.pattern && addToBagForm.qty.$touched" class="help-block">This field can only contain whole, positive numbers.</span>
						</div>
					</div>
				</div>
				<div class="ngdialog-quick-add-actions-bottom gap-2">
					<button class="bd-button bd-button-dark rounded-full w-full" type="submit">Add to Cart</button>
					<button class="bd-button bd-button-border rounded-full w-full" ng-click="closeThisDialog()">Cancel</button>
				</div>
			</form>
		</div>
	`;

	function QuickAddController(scope, client) {
		const loadProductAvailability = async function (unit = 1) {
			scope.data.busy = true;
			let result = await client.$product.availability(scope.current.Product.ProductCode, unit);
			let isAvailable = result.value.price && result.value.options.some(option => option.leadTime >= 0);
			result.value.options = result.value.options.map(i => (i.optionAvailable = !!(i.leadTime >= 0 || i.eta), i));
			scope.data.busy = false;
			return {
				...result.value,
				status: isAvailable ? scope.AS_AVAILABLE : result.value.options[0].eta ? scope.AS_BACKORDERED : scope.AS_OUTOFSTOCK
			};
		}

		const calculateTotalAmount = async function () {
			if (!scope.data.needed && scope.data.mode === scope.IM_SAMPLE) scope.data.needed = 1;

			if (!scope.data.needed) return;

			try {
				scope.busy = true;
				scope.data.totalSellQty = calculateTotalSellQty();
				scope.data.availability = await loadProductAvailability(scope.data.totalSellQty);
				scope.data.totalAmount = scope.$root.$utils.round(scope.data.totalSellQty * scope.data.availability.price.currentPrice);
				if (scope.data.availability.options.length === 1) scope.data.fulfillment = scope.data.availability.options[0].type;
			} catch (error) {
				console.error(error);
			} finally {
				scope.busy = false;
				scope.$digest();
			}
		}

		const calculateTotalSellQty = function () {
			scope.data.unit = scope.$root.$uom.adjustSellQtyToSolidBaseUnitQty(
				scope.data.needed,
				scope.current.Product.SellingUom
			);

			scope.data.sellingPerHandlingQty = scope.$root.$uom.calculateSellingPerHandlingQty(
				scope.current.Product.SellingUom,
				scope.current.Product.HandlingUom
			);

			scope.data.totalHandlingQty = (() => {
				let overage = scope.$root.$utils.round(scope.data.unit * (scope.data.overage / 100), 4);
				let total = scope.$root.$utils.round(scope.data.unit + overage, 4);
				return scope.$root.$uom.calculateTotalHandlingQty(total, scope.current.Product.SellingUom, scope.current.Product.HandlingUom);
			})();

			return (scope.sameUom()) ? (() => {
				let overage = scope.$root.$utils.round(scope.data.unit * (scope.data.overage / 100), 4);
				let total = scope.$root.$utils.round(scope.data.unit + overage, 4);
				return scope.current.Product.SellingUom.IsFractional ? total : Math.ceil(total);
			})() : scope.$root.$utils.round(scope.data.totalHandlingQty * scope.data.sellingPerHandlingQty, 4);
		}

		scope.IM_FULL = "IM_FULL";
		scope.IM_SAMPLE = "IM_SAMPLE";

		scope.data = {
			busy: true,
			unit: 0,
			overage: 0,
			needed: null,
			totalAmount: 0,
			availability: null,
			mode: scope.IM_FULL,
			totalHandlingQty: null,
			sellingPerHandlingQty: 0,
		}

		scope.sameUom = function () {
			if (!scope.current) return false;
			if (!scope.current.Product.HandlingUom || !scope.current.Product.SellingUom) return true;
			return scope.current.Product.HandlingUom.Id === scope.current.Product.SellingUom.Id;
		}

		scope.addToBag = async function (form) {
			if (form.$invalid) return;

			let selectedOption = scope.data.availability.options[0];

			scope.data.busy = true;

			let data = {
				qty: scope.data.totalSellQty,
				storeCode: selectedOption.branchNo,
				itemNo: scope.current.Product.ProductCode,
			};

			let item = {
				name: scope.current.Product.Name,
				totalAmount: scope.data.totalAmount,
				totalSellQty: scope.data.totalSellQty,
				currency: scope.current.Price.Currency,
				imageName: scope.current.Product.ImageName,
				totalHandlingQty: scope.data.totalHandlingQty,
				isSample: scope.data.mode === scope.IM_SAMPLE,
				currentPrice: scope.current.Price.CurrentPrice,
				productCode: scope.current.Product.ProductCode,
				sellingUom: scope.current.Product.SellingUom.Name,
				handlingUom: scope.current.Product.HandlingUom.Name,
			};

			await scope.$root.$shoppingbag.addItemToBag(item, data);

			scope.data.busy = false;

			setTimeout(() => scope.$digest(), 0);

			scope.closeThisDialog();
		}

		scope.handleQtyChange = async function (form, event) {
			scope.data.overage = 0;
			scope.data.needed = null;
			scope.data.totalAmount = 0;
			scope.data.availability = null;

			if (form.qty.$invalid) return;

			event.target.blur();

			let roundedHandlingQty = Math.ceil(scope.data.totalHandlingQty);

			let sellingPerHandlingQty = scope.$root.$uom.calculateSellingPerHandlingQty(
				scope.current.Product.SellingUom,
				scope.current.Product.HandlingUom
			);

			scope.data.needed = scope.$root.$utils.round(sellingPerHandlingQty * roundedHandlingQty, 2);

			await calculateTotalAmount();

			if (form.needed) form.needed.$setTouched();
		}

		scope.handleNeededChange = async function (form, event) {
			scope.data.overage = 0;
			scope.data.totalAmount = 0;
			scope.data.availability = null;
			scope.data.totalHandlingQty = null;

			if (form.needed.$invalid) return;

			event.target.blur();

			await calculateTotalAmount()

			if (form.qty) form.qty.$setTouched();
		}

		scope.$watch('data.mode', (value) => {
			if (!value) return;
			new Promise((resolve, reject) => {
				scope.data.busy = true;
				if (value === scope.IM_FULL) {
					if (scope.item) resolve(scope.item);
					else client.$product.detail(scope.code).then(data => resolve(scope.item = data), err => reject(err));
				} else if (scope.item.Product.SampleItemNo) {
					if (scope.sample) resolve(scope.sample);
					else client.$product.detail(scope.item.Product.SampleItemNo).then(data => resolve(scope.sample = data), err => reject(err));
				}
			}).then(model => scope.$apply(() => {
				scope.current = model;
				scope.data.busy = false;
				scope.item.href = scope.$root.$settings.getSecureUrl(`product/detail/${scope.item.Product.UrlFriendlyStyleName}/?itemNo=${scope.item.Product.ProductCode}`, true)
			})).catch(err => scope.$apply(() => {
				scope.data.busy = false;
				scope.data.mode = scope.IM_FULL;
			}));
		});
	}

	window.bdApp.run(['$templateCache', (cache) => cache.put('quick-add.html', template)]);

	window.bdApp.run(['$serviceInjector', (injector) => injector.inject({
		'$shoppingbag': '$shoppingbagService',
		'$uom': 'UomConversionService',
		'$settings': 'appSettings',
		'$utils': 'appUtils',
	})]);

	window.bdApp.controller('QuickAddController', ['$scope', '$frontend', QuickAddController]);
})()
;
(function () {
	'use strict';
	angular.module('app')
		.directive('addThis',
		function () {
			return function (scope, element) {
				yepnope({
					load: '//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-537c393450362103&domready=1&async=1',
					complete: function () {
						addthis.init();
						addthis.toolbox(element, {}, {
							url: scope.shareUrl
						});

						addthis.update('share', 'title', scope.shareTitle);
					
						scope.$watchGroup(['shareUrl', 'shareTitle'], function (newValues, oldValues, scope) {
							if (addthis) {
								addthis.update('share', 'url', scope.shareUrl);
								addthis.update('share', 'title', scope.shareTitle);
								addthis.update('share', 'media', scope.shareMedia);
								
							}
						});
					}
				});
			};
		});
}());
;
(function () {
	'use strict';
	
	let template = `
		<div class="pdp-page-section">
			<h2 class="pdp-page-section-title">{{model.Product.ProductSeries}} Gallery</h2>
			<bd-slider plugins="['classNames','wheelGestures']" class="pdp-page-image-gallery" items="gallery">
				<bd-slide ng-repeat="image in gallery track by $index">
					<div style="cursor:pointer;" class="pdp-page-image-gallery-item" ng-click="showCollectionImageDetail(image)">
						<bd-responsive-image width="600" alt="{{model.Product.Name}} - gallery image {{$index}}" image-src="{{image.src}}"></bd-responsive-image>
					</div>
				</bd-slide>
			</bd-slider>
		</div>
	`;
	
	window.bdApp.directive('pdpImageGallery', function () {
		return {
			template,
			scope: false,
			replace: true,
		}
	})
})();
(function () {
	'use strict';
	
	let template = `
		<ng-content-replace>
			<div class="pdp-page-main-gallery-large">
				<bd-slider plugins="['classNames','wheelGestures']" em-select="selectMainSlider" slider="mainSlider" options="mainSliderOptions">
					<bd-slide ng-repeat="image in images track by image.imageUrl">
						<bd-responsive-image width="800" ng-click="onImageClick(image)" alt="{{model.Product.Name}} - main image {{$index}}" image-src="{{image.imageUrl}}"></bd-responsive-image>
					</bd-slide>
				</bd-slider>
			</div>
			<div class="pdp-page-main-gallery-indicator">
				<bd-slider ng-show="images.length > 1" plugins="['classNames','wheelGestures']" em-init="initDotSlider" em-reinit="initDotSlider" slider="dotSlider" options="dotsSliderOptions">
					<bd-slide class="pdp-slider-dot" ng-repeat="dot in images"></bd-slide>
				</bd-slider>
			</div>
		</ng-content-replace>
	`;
	
	let fullImageTemplate = `
		<div class="pdp-page-fullimage">
			<div class="pdp-page-fullimage-main">
				<bd-slider plugins="['classNames','wheelGestures']" options="mainSliderOptions" em-select="selectMainSlider">
					<bd-slide ng-repeat="image in images track by image.zoomUrl">
						<bd-responsive-image width="1600" alt="{{model.Product.Name}} - large image {{$index}}" image-src="{{image.zoomUrl}}"></bd-responsive-image>
					</bd-slide>
				</bd-slider>
			</div>
			<div class="pdp-page-fullimage-thumbnails">
				<bd-slider slider="thumbnailSlider" plugins="['classNames','wheelGestures']" class="bd-embla-pilled" options="thumbnailsSliderOptions">
					<bd-slide ng-repeat="image in images track by image.thumbUrl">
						<bd-responsive-image width="100" alt="{{model.Product.Name}} - thumbnail image {{$index}}" image-src="{{image.thumbUrl}}"></bd-responsive-image>
					</bd-slide>
				</bd-slider>
			</div>
		</div>
	`;
	
	window.bdApp.directive('pdpImageSlider', (ngDialog) => ({
		template,
		scope: false,
		replace: true,
		controller: ($scope) => {
			$scope.thumbnailSliderOptions = {
				dots: false,
				align: 'start',
				showButtons: false,
				containScroll: 'trimSnaps',
			};
			$scope.dotsSliderOptions = {
				dots: false,
				align: 'center',
				watchDrag: false,
				showButtons: false,
				containScroll: 'keepSnaps',
			};
			$scope.mainSliderOptions = {
				dots: false,
				showButtons: false,
			};
			
			const updateClassName = (slider, className, prevSnap, selectedSnap) => {
				let nodes = slider.slideNodes();
				if (nodes[prevSnap]) nodes[prevSnap].classList.remove(className);
				if (nodes[selectedSnap]) nodes[selectedSnap].classList.add(className);
			}
			
			$scope.onImageClick = (image) => {
				let scope = $scope.$new(true);
				
				scope.images = $scope.images;
				scope.mainSliderOptions = {
					dots: false,
					startIndex: $scope.images.indexOf(image)
				};
				scope.thumbnailsSliderOptions = {
					dots: false,
					align: 'center',
					showButtons: false,
					containScroll: false,
					startIndex: $scope.images.indexOf(image)
				};
				
				let controller = function ($scope) {
					$scope.selectMainSlider = (slider) => {
						let prevSnap = slider.previousScrollSnap();
						let selectedSnap = slider.selectedScrollSnap();
						
						if ($scope.thumbnailSlider) {
							updateClassName($scope.thumbnailSlider, 'is-pill', prevSnap, selectedSnap);
							if (selectedSnap !== $scope.thumbnailSlider.selectedScrollSnap()) $scope.thumbnailSlider.scrollTo(selectedSnap);
						}
					}
				}
				
				ngDialog.open({
					scope,
					controller,
					plain: true,
					template: fullImageTemplate,
					className: 'ngdialog-theme-plain ngdialog-pdp-fullimage',
				});
			}
			
			$scope.initDotSlider = (slider) => {
				let nodes = slider.slideNodes().map(node => (node.classList.remove('active'), node));
				let selectedSnap = $scope.mainSlider ? $scope.mainSlider.selectedScrollSnap() : 0;
				nodes[selectedSnap].classList.add('active');
			}
			
			$scope.selectMainSlider = (slider) => {
				let prevSnap = slider.previousScrollSnap();
				let selectedSnap = slider.selectedScrollSnap();
				
				if ($scope.dotSlider) {
					updateClassName($scope.dotSlider, 'active', prevSnap, selectedSnap);
					if (selectedSnap !== $scope.dotSlider.selectedScrollSnap()) $scope.dotSlider.scrollTo(selectedSnap);
				}
				
				if ($scope.thumbnailSlider) {
					updateClassName($scope.thumbnailSlider, 'is-pill', prevSnap, selectedSnap);
					if (selectedSnap !== $scope.thumbnailSlider.selectedScrollSnap()) $scope.thumbnailSlider.scrollTo(selectedSnap);
				}
			}
			
			$scope.initThumbnailSlider = (slider) => {
				let nodes = slider.slideNodes().map(node => (node.classList.remove('is-pill'), node));
				let selectedSnap = ($scope.mainSlider) ? $scope.mainSlider.selectedScrollSnap() : 0;
				nodes[selectedSnap].classList.add('is-pill');
				nodes.map((node, index) => node.addEventListener('click', () => $scope.mainSlider.scrollTo(index)));
			}
		}
	}))
})();
(function () {
	'use strict';

	let template = `
		<bd-product-slider
			header="You Recently Viewed"
			items="items"
			root-class="bd-recommendations"
			title-class="bd-recommendations-title"
			container-class="bd-recommendations-container"
			item-class="bd-recommendations-item" />
	`;

	window.bdApp.directive('pdpRecentlyViewed', ['recentProductsService', function (service) {
		return {
			template,
			scope: true,
			link: (scope) => {
				scope.$watch('itemNo', () => {
					scope.items = (service.GetRecentItemsByKey()).map(item => ({
						...item,
						uom: item.sellingUom ? item.sellingUom.Name : null,
						currentPrice: item.priceToDisplay ? item.priceToDisplay.CurrentPrice : null,
						image: `https://res.cloudinary.com/bedrosians/image/upload/f_auto,t_product_300/v1/cdn-bedrosian/assets/products/hiresimages/${item.imageName}`,
					}))
				})
			},
		}
	}])
})()
;
(function(){
	'use strict';

	window.bdApp.service('$addSampleDialog', function ($q, $api, $rootScope, $frontend, $templateCache, $shoppingbagService, ngDialog) {

		let template = `
			<div class="modal">
				<div class="modal__content">
					<div ng-if="item || busy" class="sample-item progress-enabled" ng-class="{'skeletron-loader': busy, 'busy': inProgress}">
						<div class="sample-item-image skeletron-image">
							<img alt="{{item.Name}}" ng-src="//res.cloudinary.com/bedrosians/image/upload/f_auto,t_product_300/v1/cdn-bedrosian/assets/products/hiresimages/{{item.ImageName}}" />
						</div>
						<div class="sample-item-description">
							<p class="sample-item-title">{{item.Name}}</p>
							<p class="sample-item-code">{{item.ProductCode}}</p>
							<p class="sample-item-price">{{sampleAvailability.price.currentPrice | currency}} / {{item.SellingUom.Id}}</p>
							<p class="sample-item-disclaimer" ng-if="item.disclaimer">Disclamer: {{item.disclaimer}}</p>
							<div class="sample-item-actions" ng-if="!$scope.sampleAvailability.isNotAvailableForOrdering && !busy">
								<bd-button ng-disabled="inProgress" ng-click="addToBag()" variant="dark">Add to Cart</bd-button>
								<bd-button ng-disabled="inProgress" ng-click="closeThisDialog()" variant="gray">Cancel</bd-button>
							</div>
						</div>
					</div>
					<div ng-if="!item && !busy" class="sample-item sample-item-exception">
						<div class="sample-item-description">
							<p class="sample-item-exception-title">Unable to order sample at that time. Please try again later.</p>
							<div class="sample-item-actions sample-item-exception-actions" ng-if="!$scope.sampleAvailability.isNotAvailableForOrdering && !busy">
								<bd-button ng-disabled="inProgress" ng-click="closeThisDialog()" variant="gray">Cancel</bd-button>
							</div>
						</div>
					</div>
				</div>
			</div>
		`;

		$templateCache.put('add-sample-item-dialog', template);

		return {
			showDialog: (sampleNo) => {
				let scope = $rootScope.$new(true);

				const controller = function ($scope) {
					$scope.busy = true;

					$q.all([$frontend.$product.detail(sampleNo), $frontend.$product.availability(sampleNo, 1)])
						.then(([item, sampleAvailability]) => {
							if(item.__meta__.status !== 200) return;

							$scope.item = item.Product;
							$scope.sampleAvailability = sampleAvailability.value;

							$scope.bagItem = {
								isSample: true,
								totalSellQty: 1,
								hasCrossSell: false,
								name: $scope.item.Name,
								imageName: $scope.item.ImageName,
								productCode: $scope.item.ProductCode,
								sellingUom: $scope.item.SellingUom.Id,
								currency: $scope.sampleAvailability.price.currency,
								totalAmount: $scope.sampleAvailability.price.currentPrice,
								currentPrice: $scope.sampleAvailability.price.currentPrice,
							};
						})
						.finally(() => $scope.busy = false);

					$scope.addToBag = () => {
						!$scope.inProgress && !$scope.sampleAvailability.isNotAvailableForOrdering
						&& $shoppingbagService.addItemToBag($scope.bagItem, {itemNo: sampleNo, qty: 1})
							.finally(() => $scope.closeThisDialog());

						$scope.inProgress = true;
					}
				};

				ngDialog.open({
					scope,
					controller,
					showClose: false,
					className: "add-sample-popup",
					template: 'add-sample-item-dialog',
				});
			}
		}
	});
})()
;
(function () {
	'use strict';

	window.bdApp.service('$itemAddedDialog', function (ngDialog, $rootScope, $templateCache, $hidePricesState, appSettings) {
		let template = `
			<div class="modal">
				<div class="modal__content">
					<div class="add-to-cart" ng-class="{'skeletron-loader': false}">
						<div class="add-to-cart-header">
							<svg class="add-to-cart-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
								<path d="M10 0C4.47711 0 0 4.47711 0 10C0 15.5229 4.47711 20 10 20C15.5229 20 20 15.5227 20 10C20 4.47733 15.5227 0 10 0ZM14.726 7.28889L9.69867 13.7951C9.53978 14.0009 9.30622 14.1144 9.06467 14.1336C8.75622 14.1767 8.43356 14.0611 8.23244 13.7971L5.26911 9.90889C4.97289 9.52 5.04844 8.95956 5.43733 8.66311C5.82622 8.36689 6.38667 8.44244 6.68311 8.83133L8.96956 11.8316L13.3193 6.20222C13.6182 5.81533 14.1793 5.74333 14.5662 6.04244C14.9531 6.34156 15.0249 6.902 14.726 7.28889Z" fill="#27B510"/>
							</svg>
							<span class="mega">Added to Cart</span>
						</div>
						<div class="add-to-cart-item" style="margin-top:25px">
							<img ng-src="https://res.cloudinary.com/bedrosians/image/upload/f_auto,t_product_300/v1/cdn-bedrosian/assets/products/hiresimages/{{data.imageName}}" alt="{{data.name}}" class="add-to-cart-image">
							<div class="add-to-cart-item-description">
								<div class="add-to-cart-item-title">
									<span>{{data.productCode}}</span>
									<span style="font-weight:700">{{data.name}}</span>
								</div>
								<span class="add-to-cart-item-price">{{data.currentPrice | currency }} / {{data.sellingUom}}</span>
								<div class="add-to-cart-item-qty">
									<span style="font-weight:700">Qty.</span>
									<span ng-if="data.totalHandlingQty">{{data.totalSellQty | number: 2}} {{data.sellingUom}} / {{data.totalHandlingQty}} {{data.handlingUom}}</span>
									<span ng-if="!data.totalHandlingQty">{{data.totalSellQty}} {{data.sellingUom}}</span>
								</div>
							</div>
						</div>
						<div ng-if="!$hidePricesState" class="add-to-cart-subtotal"><strong>Subtotal:</strong> <span style="margin-left:40px">{{data.totalAmount | currency}}</span></div>
					</div>
					<bd-recommendations
						use-skeleton="true"
						header="Complete Your Project"
						relation-type="BoughtTogether"
						items-no="[data.productCode]" class="add-item-popup-recommendations">
					</bd-recommendations>
				</div>
				<div class="modal__footer" ng-if="!data.crossSell.length || data.isSample">
					<bd-button href="{{shoppingbagUrl}}" variant="gray">View Cart</bd-button>
					<bd-button href="{{checkoutUrl}}" variant="dark">Checkout</bd-button>
					<bd-button class="sm-order" style="margin-right:auto" ng-click="closeThisDialog(null)" variant="gray-link">Keep Shopping</bd-button>
				</div>
			</div>
		`;

		$templateCache.put('item-added-dialog', template);

		return {
			showDialog: (item) => {
				let scope = $rootScope.$new(true);

				scope.data = item;
				scope.checkoutUrl = appSettings.getSecureUrl('checkout', true);
				scope.shoppingbagUrl = appSettings.getSecureUrl('shoppingbag', true);

				ngDialog.open({
					scope,
					showClose: false,
					template: 'item-added-dialog',
					className: "add-to-card-popup",
				});
			}
		}
	});
})();
;
(function () {
	'use strict';

	window.bdApp.service('$productOptionsService', function ($api, $location, $requestBuilders) {
		// privates
		this.$$navigateToItem = function (item) {
			let $item = Object.fromEntries(Object.entries(item)
				.map((a) => [a[0].charAt(0).toUpperCase() + a[0].slice(1), a[1]]));
			$location.search('itemNo', $item.ProductCode);
			$location.state($item);
		}

		// public
		this.getOptionImage = function (option) {
			return `https://res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/${option.imageName}`;
		}

		this.thicknessOptions = function () {
			return this.$$options.value.products
				.filter(item => (
					item.materialFinish === this.model.Product.MaterialFinish
				))
				.reduce((result, item) => {
					return (result.some(_item => (
						_item.thickness === item.thickness
					))) ? result : (result.push(item), result);
				}, [])
				.sort((a, b) => a.thickness > b.thickness ? 1 : a.thickness === b.thickness ? 0 : -1);
		}
		this.finishOptions = function () {
			let firstOptions = this.$$options.value.products
				.filter(x =>
					x.size === this.current.size
					&& x.shape === this.current.shape
					&& x.seriesColor === this.current.seriesColor
				);

			let secondOptions = this.$$options.value.products
				.sort((a, b) => a.seriesColor > b.seriesColor ? 1 : a.seriesColor === b.seriesColor ? 0 : -1)
				.filter(x => !firstOptions.some(y => y.seriesColor === x.seriesColor));

			return [
				...firstOptions,
				...secondOptions,
			].reduce((result, item) => {
				return (result.some(_item => (
					_item.materialFinish === item.materialFinish
				))) ? result : (result.push(item), result);
			}, []).sort((a, b) => a.materialFinish > b.materialFinish ? 1 : a.materialFinish === b.materialFinish ? 0 : -1);
		}
		this.colorOptions = function () {
			let firstOptions = this.$$options.value.products.filter(item => (
				item.size === this.model.Product.Size
				&& item.shape === this.model.Product.Shape
				&& item.mosaicSize === this.model.Product.MosaicSize
				&& item.materialFinish === this.model.Product.MaterialFinish
			))
				.sort((a, b) => a.seriesColor > b.seriesColor ? 1 : a.seriesColor === b.seriesColor ? 0 : -1)
				.sort((a, b) => a.shape > b.shape ? 1 : a.shape === b.shape ? 0 : -1)
				.sort((a, b) => parseInt(b.size.split('x')[0]) - parseInt(a.size.split('x')[0]));

			let secondOptions = this.$$options.value.products.filter(x => (
				!firstOptions.some(y => y.seriesColor === x.seriesColor)
				&& x.materialFinish === this.model.Product.MaterialFinish
			))
				.sort((a, b) => a.seriesColor > b.seriesColor ? 1 : a.seriesColor === b.seriesColor ? 0 : -1)
				.sort((a, b) => a.shape > b.shape ? 1 : a.shape === b.shape ? 0 : -1)
				.sort((a, b) => parseInt(b.size.split('x')[0]) - parseInt(a.size.split('x')[0]));

			return [
				...firstOptions,
				...secondOptions,
			].reduce((result, item) => {
				return (result.some(_item => (
					_item.seriesColor === item.seriesColor
				))) ? result : (result.push(item), result);
			}, [])
				.sort((a, b) => a.seriesColor > b.seriesColor ? 1 : a.seriesColor === b.seriesColor ? 0 : -1);
		}
		this.shapeOptions = function () {
			return this.$$options.value.products
				.filter(item => (
					item.seriesColor === this.model.Product.SeriesColor
					&& item.materialFinish === this.model.Product.MaterialFinish
				))
				.reduce((result, item) => {
					return (result.some(_item => (
						_item.size === item.size
						&& _item.shape === item.shape
						&& _item.mosaicSize === item.mosaicSize
						&& _item.materialFinish === item.materialFinish
						&& _item.materialCategory === item.materialCategory
					))) ? result : (result.push(item), result);
				}, [])
				.sort((a, b) => a.shape > b.shape ? 1 : a.shape === b.shape ? 0 : -1)
				.sort((a, b) => parseInt(b.size.split('x')[0]) - parseInt(a.size.split('x')[0]));
		}

		this.finishChanged = function () {
			let items = this.$$options.value.products.filter(x =>
				x.size === this.current.size
				&& x.shape === this.current.shape
				&& x.seriesColor === this.current.seriesColor
				&& x.materialFinish === this.current.materialFinish
			);
			if (!items) items = this.$$options.value.products.filter(x => x.materialFinish === this.current.materialFinish);
			items = items.sort((a, b) => a.shape > b.shape ? 1 : a.shape === b.shape ? 0 : -1)
				.sort((a, b) => parseInt(b.size.split('x')[0]) - parseInt(a.size.split('x')[0]))
				.sort((a, b) => a.seriesColor > b.seriesColor ? 1 : a.seriesColor === b.seriesColor ? 0 : -1);
			this.current = items[0];
			this.$$navigateToItem(this.current);
		}

		this.optionChanged = function () {
			this.$$navigateToItem(this.current);
		}

		this.init = async function (model) {
			this.model = model;

			this.current = Object.fromEntries(Object.entries(model.Product)
				.map((a) => [a[0].charAt(0).toLowerCase() + a[0].slice(1), a[1]]));

			if (this.$$options || !this.model.Product.GroupVariantsBy) return this;

			let requestBuilder = $requestBuilders.$webproductListRequestBuilder();
			requestBuilder.addFacet('GroupVariantsByValue', this.model.Product.GroupVariantsBy);
			requestBuilder.setDisableFacets(true);

			this.$$options = await $api.$webproduct.list(requestBuilder.make(), model.Product.ProductSeries);

			return this;
		}
	})
})()
;
(function () {
	'use strict'
	
	const QuickAddService = ($scope, $dialog) => ({
		open(code) {
			const scope = $scope.$new(true);
			
			scope.code = code;
			scope.current = {Product: $scope.$model.products.find(x => x.ProductCode === code)};
			
			$dialog.open({
				scope,
				showClose: false,
				template: 'quick-add.html',
				controller: 'QuickAddController',
				className: 'ngdialog-theme-plain ngdialog-quick-add',
			});
		}
	})
	
	window.bdApp.factory('QuickAddService', ['$rootScope', 'ngDialog', QuickAddService]);
})();
(function () {
	'use strict';

	function recentProductsService() {
		let self = this;

		let recentlyViewedProductsKey = 'RecentlyViewedProducts';

		// get recently viewed items from localStorage
		function GetRecentItemsByKey() {
			let reload = localStorage.getItem('recentReloadedNext');
			if (!reload || reload !== 'true') localStorage.removeItem(recentlyViewedProductsKey);
			localStorage.setItem('recentReloadedNext', 'true');
			let data = localStorage.getItem(recentlyViewedProductsKey);
			return data ? JSON.parse(data) : [];
		}

		// order by recent date
		self.OrderByDescDate = function (date1, date2) {
			if (date1.Updated > date2.Updated) return -1;
			if (date1.Updated < date2.Updated) return 1;
			return 0;
		};

		// add or update item into localStorage
		function AddOrUpdateRecent(value) {
			let items = this.GetRecentItemsByKey() || [];

			let filter = $.map(items, function (item) {
				if (item.ProductCode === value.ProductCode) {
					return item.Updated = new Date().toUTCString();
				}
			});

			if (filter.length === 0) {
				items.push(value);
			}

			// check recent items limit
			if (items.length >= 10) {
				items = items.sort(self.OrderByDescDate);
				items.splice(items.length - 1, 1);
			}

			localStorage.setItem(recentlyViewedProductsKey, JSON.stringify(items));
		}

		return {
			GetRecentItemsByKey: GetRecentItemsByKey,
			AddOrUpdateRecent: AddOrUpdateRecent
		};
	}

	window.bdApp.service('recentProductsService', [recentProductsService]);
})();
;
(function () {
	'use strict';

	window.bdApp.service('relatedItemsServices', ['$api', 'appSettings', function ($api, appSettings) {
		this.ids = [];
		this.items = [];
		this.relatedTypes = null;
		this.getItems = function (value, type) {
			if (!_.isEqual(this.ids, value)) this.items = [];
			if (this.relatedTypes !== type) this.items = [];
			this.ids = value;
			return this.items.length > 0 ? Promise.resolve(this.items)
				: $api.$webproduct.getrelateditems(type, value, true).then(result => {
					this.items = (result.value || []).map(item => ({
						...item,
						uom: item.sellingUom ? item.sellingUom.name : null,
						currentPrice: item.priceToDisplay ? item.priceToDisplay.currentPrice : null,
						href: appSettings.getUrl(`product/detail/${item.urlFriendlyStyleName ? item.urlFriendlyStyleName + '/' : '/'}?itemNo=${item.productCode}`, true),
						image: `https://res.cloudinary.com/bedrosians/image/upload/f_auto,t_product_300/v1/cdn-bedrosian/assets/products/hiresimages/${item.imageName}`,
					}));
					return this.items;
				});
		}
	}]);
})()
;
(function () {
	'use strict';
	
	window.bdApp.service('$shoppingbagService', function ($q, $frontend, $rootScope, $itemAddedDialog, googleTagManagerService) {
		return {
			addItemToBag: async function (item, data) {
				let result = await $frontend.$shoppingbag.addToBag(data);
				
				$rootScope.$broadcast('shoppingBagItemsChanged', result.value);
				
				let eventId = result.__meta__.headers('Tags_EventId');
				
				//Pushing data to Google Tag Manager Service:
				googleTagManagerService.ItemAddedEvent(data.itemNo, data.qty, item.sellingUom,
					item.totalAmount, item.currency, eventId, true);
				
				if (result.success) $itemAddedDialog.showDialog(item);
				else alert(result.messages);
			},
		}
	});
})();;
(function () {
	'use strict';

	function ShoppingBagCtrl($scope, $filter, ngDialog, $window, spinner, appSettings, $http, shoppingBagItems, $api) {

		$scope.itemsNo = shoppingBagItems.map(i => i.Sku.ProductCode);

		// $api.$webproduct.getrelateditems('CROSSSELL', ids).then(res => {
		// 	if (res.__meta__.status !== 200 || !res.success) return;
		// 	$scope.crossSell = res.value.map(item => {
		// 		item.href = appSettings.getUrl("product/detail/" + item.urlFriendlyStyleName + "/?itemNo=" + item.productCode, true);
		// 		item.image = '//res-5.cloudinary.com/bedrosians/image/upload/f_auto,t_product_300/v1/cdn-bedrosian/assets/products/hiresimages/' + item.imageName;
		// 		return item;
		// 	});
		// });

		$scope.saveToShoppingBag = function () {
			ngDialog.open({
				template: '/save-shopping-bag-added.html',
				className: 'ngdialog-theme-plain save-to-shoppingbag-dialog',
				scope: $scope
			});
		};

		$scope.addCurrentBagToWishList = function (name, note) {
			if (!name) {
				$window.alert('Enter name for a New Shopping Bag.');
				return;
			}
			spinner.startLoad();
			var model = {
				name: name,
				note: note
			};
			var url = appSettings.getUrl('WishList/AddCurrentBagToWishList', true);
			$http({
				method: 'POST',
				url: url,
				data: model
			}).then(function successCallback(result) {
				if (!result.data.errors) {
					$window.location.reload();
				} else {
					$window.alert(result.data.errors.Messages[0]);
					spinner.endLoad();
				}
			}, function errorCallback(response) {
				$window.alert(response.statusText);
				spinner.endLoad();
			});
		};

		$scope.saveForLater = function (data) {
			$scope.data = data;
			ngDialog.open({
				template: '/save-for-later.html',
				className: 'ngdialog-theme-plain save-for-later-dialog',
				scope: $scope
			});
		};

		$scope.proceedForCheckout = function (data) {
			$scope.data = data;
			ngDialog.open({
				template: '/proceed-to-checkout.html',
				className: 'ngdialog-theme-plain proceed-to-checkout-dialog',
				scope: $scope
			});
		};
	}

	angular.module('app').controller('ShoppingBagCtrl', ['$scope', '$filter', 'ngDialog', '$window', 'spinner', 'appSettings', '$http', 'shoppingBagItems', '$api', ShoppingBagCtrl]);
})();
;
(function () {
	"use strict";
	
	angular.module("app").directive("oepSignUp", oepSignUp);
	
	function oepSignUp($http, $compile, $cookies, ngDialog, appSettings, myModuleConst) {
		return {
			replace: true,
			restrict: "EA",
			scope: { siteKey: "=", asLink: "=" },
			link: function (scope, element) {
				
				if(!scope.asLink) {
					$http.get(appSettings.getUrl(myModuleConst.oepSignUpEmailTemplatePath, false)).then(({data}) => {
						let view = $compile(data)(scope);
						element.append(view);
					});
				} else {
					element.get(0).addEventListener('click', () => scope.signUpDialog());
				}
				
				scope.url = appSettings.getUrl("subscription/subscribe/", true);
				
				scope.signUpDialog = () => {
					if(scope.isBusy) return;
					
					scope.isBusy = true;
					
					ngDialog.open({
						scope: scope,
						closeByEscape: true,
						closeByDocument: true,
						controller: "SubscribeModalCtrl",
						className: "ngdialog-theme-plain email-signup",
						template: appSettings.getUrl(myModuleConst.subscribeModalTemplatePath, false),
					});
				}
				
				var cookieKey = "OepEmailSignup";
				if($cookies.get(cookieKey) || document.body.classList.contains('hide-menu') || scope.asLink) return;
				
				scope.signUpDialog();
				
				var expDate = Date.now() + 300 * 24 * 60 * 60 * 1000;
				$cookies.put(cookieKey, expDate, {expires: new Date(expDate)});
			},
		};
	}
})();
;
(function () {
	"use strict";
	
	angular.module("app").controller("SubscribeModalCtrl", SubscribeModalCtrl);
	
	function SubscribeModalCtrl($scope, $http, $timeout, appSettings, googleTagManagerService) {
		$scope.$parent.isBusy = $scope.isBusy = false;
		
		if(!$scope.data) $scope.data = {};
		
		if(!$scope.url || !$scope.types) {
			$scope.isBusy = true;
			$scope.url = appSettings.getUrl("subscription/subscribe/", true);
			$http.get($scope.url).then(res => $scope.types = res.data.subscriptions).finally(() => $scope.isBusy = false);
		}
		
		const send = () => {
			$http.post($scope.url, $scope.data).then(res => {
					var {success, messages} = res.data;
					
					if(success) $scope.confirm = true;
					else $scope.messages = messages;
					
					if(success) googleTagManagerService.EmailSignupSuccess();
					else googleTagManagerService.ErrorEvent($scope.messages.join(','))
				})
				.catch(err => googleTagManagerService.ErrorEvent(err))
				.finally(() => $scope.isBusy = false);
		};
		
		$scope.next = () => {
			$scope.full = true;
		}
		
		$scope.submitForm = () => {
			$scope.isBusy = true
			
			if(!grecaptcha) {
				$scope.data.recaptchaError = 'Google Recaptcha is not initialized';
				return send();
			}
			
			grecaptcha.ready(() => {
				grecaptcha.execute($scope.siteKey, {action: "Subscribe"}).then(token => {
					$scope.data.recaptchaToken = token;
					$scope.data.subscriptionSourceId = $scope.types.filter(x => x.isSubscribed).map(x => x.id);
				}, err => {
					$scope.data.recaptchaError = err
					googleTagManagerService.ErrorEvent(err);
				}).then(send);
			});
		}
	}
})();
;
(function () {
	'use strict';

	angular.module('app').controller('SiteSearchController', SiteSearchController);

	SiteSearchController.$inject = ['$scope','$http', '$location', 'appSettings','spinner', 'searchModel'];

	function SiteSearchController($scope, $http, $location, appSettings, spinner, searchModel) {

		$scope.model = {
			pageSizes: [20, 50, 100, 200],
			pageSize: 20,
			currentPage : 1,
			totalPages : 1,
			query: searchModel.query,
			totalCount: 0
		};
		$scope.items = [];
		$scope.getSearchResult = getSearchResult;
		$scope.setPageSize = setPageSize;

		init();

		$scope.prevPage = function () {
			if ($scope.model.currentPage > 1) {
				$scope.model.currentPage--;
			}
			$scope.getSearchResult();
		};

		$scope.prevPageDisabled = function () {
			return $scope.model.currentPage === 1 ? "disabled" : "";
		};

		$scope.nextPage = function () {
			$scope.model.currentPage++;
			$scope.getSearchResult();
		};

		$scope.nextPageDisabled = function () {
			return $scope.model.pageSize > $scope.items.length ? "disabled" : "";
		};

		function init() {
			getSearchResult();
		}

		function setPageSize(size) {
			$scope.model.pageSize = size;
			$scope.model.currentPage = 1;
			getSearchResult();
		}

		function getSearchResult() {
			spinner.startLoad();

			$http({
				method: 'GET',
				url: appSettings.getUrl('search/content/?q=' + $scope.model.query + "&page=" + $scope.model.currentPage + "&pageSize="+$scope.model.pageSize, true),
				headers: {
					'X-Requested-With': 'XMLHttpRequest'
				}
			}).then(function (response) {
					var data = { items: [], pageFoundCount: 0 };

					data.totalCount = response.data.totalCount;

					response.data.items.forEach(function (element) {
						var item = {
							url: element.url,
							title: element.title,
							description: element.description
						};
						data.items.push(item);
					});

					$scope.items = data.items;
					$scope.model.totalCount = data.totalCount;
					$scope.model.totalPages = Math.ceil(data.totalCount / $scope.model.pageSize);

			}, function (error) {
					console.log(error);
			})
			.finally(function() {
				spinner.endLoad();
			});
		}
	}
})();
;
(function () {
	'use strict';

	angular
		.module('app')
		.controller('SlabYardCtrl', SlabYardCtrl);

	function SlabYardCtrl($scope, $cookies, $window, $location, model, oepFilterService) {

		$scope.model = model;

		const check = (filters, reload) => {
			let search = $location.search();
			for (let key in search) key.includes('f_') && delete search[key];
			$location.search({...search, ...filters});
			$location.state(reload);
		}

		oepFilterService.setRefinements($window.slabYard.refinements);

		oepFilterService.onChanged((filters) => {
			$scope.$emit('oep.filter.busy');
			check(filters, true);
		});

		$scope.$on('$locationChangeSuccess', (e, a, b, c) => {
			return c && $window.location.reload()
		});

		$scope.$emit('oep.filter.ready');

		// remove unselected filter
		let filters = oepFilterService.getFilters();
		check(filters, false);

		oepFilterService.init(true);
	}
}());
;
(function () {
	'use strict';

	function StatementsCtrl($scope, StatementsService, spinner, $http, ngDialog, $q, appSettings, $window) {
		$scope.init = init;
		$scope.statements = [];
		$scope.statementsCache = [];
		$scope.parentCustomer = {};
		$scope.customerBranches = [];
		$scope.selectedBranch = {};
		$scope.getStatements = getStatements;
		$scope.selectedYear = null;
		$scope.startDateIsActive = false;
		$scope.dateRangeIsActive = false;
		
		$scope.itemsPerPageList = [
			{ Value: 20, Name: "Per page: 20" },
			{ Value: 50, Name: "Per page: 50" },
			{ Value: 100, Name: "Per page: 100" },
			{ Value: 200, Name: "Per page: 200" },
		];

		$scope.currentPage = 0;

		$scope.model = {
			itemsPerPage: $scope.itemsPerPageList[0],
			loadingStatements: false,
			filterError: '',
		}	
		
		function getStatements() {
			spinner.startLoad();
			
			$scope.model.filterError = ''; // need to show errors after validation for inputs 
			$scope.model.loadingStatements = true;

			var params = {
				year: $scope.selectedYear ? $scope.selectedYear.value : new Date().getFullYear(),
				itemsPerPage: $scope.model.itemsPerPage.Value,
				customerBranchId: $scope.selectedBranch.Id,
				page: $scope.currentPage,
			};

			$scope.statements = $scope.statementsCache = null;

			StatementsService.getStatements(params).then(function (result) {

				$scope.togglePage = false;
				$scope.toggleStatus = false;
				$scope.toggleDisplay = false;

				$scope.statements = $scope.statementsCache = result.Statements;
				$scope.customerBranches = result.CustomerBranches;

				var currentYear = new Date().getFullYear();

				$scope.availableYears = result.AvailableYears.map(function (x) {
					return {
						name: (x == currentYear ? 'Year to Date' : x),
						value: x
					};
				});

				if (!$scope.selectedYear) $scope.selectedYear = $scope.availableYears[0];

				$scope.selectedBranch = $.grep($scope.customerBranches, function (n) {
					return n.Id === result.Customer.Id;
				})[0];

				$scope.parentCustomer = {
					CustomerName: result.Customer.ParentCustomerName
				};
			}, function (error) {
				console.log(error);
			}).finally(function () {
				spinner.endLoad();
				$scope.model.loadingStatements = false;
			});
		}

		//pagination
		$scope.prevPage = function () {
			if ($scope.currentPage > 0) {
				$scope.currentPage--;
			}
			$scope.getStatements();
		};

		$scope.prevPageDisabled = function () {
			return $scope.currentPage === 0 ? "disabled" : "";
		};

		$scope.nextPage = function () {
			$scope.currentPage++;
			$scope.getStatements();
		};

		$scope.nextPageDisabled = function () {
			if ($scope.statements) {
				return $scope.model.itemsPerPage.Value > $scope.statements.length ? "disabled" : "";
			}
			return "disabled";
		};

		$scope.customerBranchChanged = function () {
			$scope.selectedYear = $scope.availableYears[0];
			$scope.applyFilter();
		}

		$scope.applyFilter = function () {
			$scope.currentPage = 0;
			$scope.getStatements();
		}

		function init() {
			getStatements();
		}

		init();
	}
	
	window.bdApp.controller('StatementsCtrl', ['$scope', 'StatementsService', 'spinner', '$http', 'ngDialog', '$q', 'appSettings', '$window', StatementsCtrl]);

})();;
(function () {
	'use strict';

	function StatementsService(appSettings, $http, $q) {

		function getStatements(params) {
			var def = $q.defer();
			$http({
					url: appSettings.getUrl("Account/Statements", true),
					method: 'GET',
					params: params,
					dataType: 'json'
				}).success(function (data) {
					if (data) {
						def.resolve(data);
					} else {
						def.reject("Failed to get statements!");
					}
				})
				.error(function () {
					def.reject("An error occurred while sending your enquiry. Please try again or contact an administrator.");
				});
			return def.promise;
		}

		return {
			getStatements: getStatements
		}
	}

	angular.module('app')
		.service('StatementsService', ['appSettings', '$http', '$q', StatementsService]);
})();;
(function() {
	'use strict';
	
	angular
		.module('app.storelocator', ['uiGmapgoogle-maps', 'app.utils'])
		.config(['uiGmapGoogleMapApiProvider', function(uiGmapGoogleMapApiProvider) {
			uiGmapGoogleMapApiProvider.configure({
				key: 'AIzaSyC4dFr0sRPsCQQ44GBo9lDJWtFH3mLmDv0',
				v: '3.54',
				libraries: 'geometry,visualization,places'
			});
			delete uiGmapGoogleMapApiProvider.options.sensor;
		}]);
}());
;
(function () {
	'use strict';

	angular
		.module('app.storelocator')
		.controller('LocationDetailCtrl', ['$scope', '$http', 'location', 'markerService', 'spinner', 'appSettings', LocationDetailCtrl]);

	function LocationDetailCtrl($scope, $http, location, markerService, spinner, appSettings) {
		spinner.startLoad();
		$scope.isInitialized = false;
		$scope.zoomIn = zoomIn;
		$scope.zoomOut = zoomOut;
		$scope.location = location;

		$scope.init = function (branchNo) {
			if (branchNo == location.locationcode) {
				$scope.isMyLocation = true;
			}
		};

		function deg2rad(deg) {
			return deg * (Math.PI / 180);
		}

		function getDistanceFromLatLonInMi(lat1, lon1, lat2, lon2) {
			var R = 3959; // Radius of the earth in miles
			var dLat = deg2rad(lat2 - lat1);  // deg2rad below
			var dLon = deg2rad(lon2 - lon1);
			var a =
			  Math.sin(dLat / 2) * Math.sin(dLat / 2) +
			  Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
			  Math.sin(dLon / 2) * Math.sin(dLon / 2);

			var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
			var d = R * c; // Distance in mi
			return d;
		}

		var previousLocation = localStorage.previousLocation;
		if (previousLocation) {
			var prevLoc = JSON.parse(previousLocation);
			
			if (prevLoc.id !== location.id) {
				var distance = getDistanceFromLatLonInMi(prevLoc.latitude, prevLoc.longitude, location.latitude, location.longitude);
				$scope.distancePrevious = Math.round(Math.abs(distance));
				$scope.locationPrevious = location.name;
			}
		}
		localStorage.previousLocation = JSON.stringify(location);

		$scope.store = null;
		$scope.markers = [];
		$scope.options = {
			scrollwheel: false,
			disableDefaultUI: true
		};

		$scope.markerOptions = {};

		$scope.changeLocation = function () {
			var url = appSettings.getUrl("shipping/changeLocation/", true);
			$http.post(url, { id: location.locationcode })
				.success(function () {
					$scope.isMyLocation = true;
				});
		};

		$scope.getHours = function (timeOfOperation) {
			var operations;
			if (!timeOfOperation) {
				operations = "-";
			}
			else {
				operations = timeOfOperation
					.replace("Monday", "M")
					.replace("Tuesday", "Tu")
					.replace("Wednesday", "W")
					.replace("Thursday", "Th")
					.replace("Friday", "F")
					.replace("Saturday", "Sat")
					.replace("Sunday", "Sun")
					.replace("MO", "M")
					.replace("TU", "Tu")
					.replace("WE", "W")
					.replace("TH", "Th")
					.replace("FR", "F")
					.replace("SA", "Sat")
					.replace("SU", "Sun")
					.replace("CLOSED", "Closed");
			}
			return operations.split('\n');
		};

		initStore(location);

		markerService.initMarkers($scope.markerOptions)
			.then(function () {
				spinner.endLoad();
				$scope.isInitialized = true;
			});

		function zoomIn() {
			$scope.map.zoom = $scope.map.zoom + 1;
		}

		function zoomOut() {
			if ($scope.map.zoom > 3) {
				$scope.map.zoom = $scope.map.zoom - 1;
			}
		}

		$scope.relativeWorkTime = "";

		function formatPhoneNumber(phoneNumberString) {
			var cleaned = ('' + phoneNumberString).replace(/\D/g, '');
			var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
			if (match) return `(${match[1]})${match[2]}-${match[3]}`;
			return null;
		}

		function initStore(store) {
			spinner.progress();

			$scope.store = store;

			$scope.store.phone = formatPhoneNumber($scope.store.phone);

			if (store) {
				$scope.googleStoreDirections = 'https://www.google.com/maps/dir/Current+Location/'
					+ encodeURIComponent(store.street + ', ' + store.city + ', ' + store.state + ' ' + store.zip);

				$scope.map = {
					center: { latitude: store.latitude, longitude: store.longitude },
					zoom: 16
				};
				if (store.isexternalbrand) {
					store.icon = {
						url: store.externalBrandDetails.Icon,
					};
				} else {
					store.icon = {
						url: '//res.cloudinary.com/bedrosians/image/upload/assets/content/icons/location_icon.svg',
					};
				}

				if (store.streetViewImageUrl == null) {
					store.streetViewImageUrl = '//maps.googleapis.com/maps/api/streetview?size=350x250&location=' +
						store.latitude +
						',' +
						store.longitude +
						'&heading=227.32&pitch=-0.76';
				}

				$scope.markers.push(store);

			} else {
				$scope.map = {
					center: { latitude: 33.815556, longitude: -117.889723 },
					zoom: 8
				};
			}

			spinner.progress();
		}
	}
}());
;
(function () {
	'use strict';

	function formatPhoneNumber(phoneNumberString) {
		var cleaned = ('' + phoneNumberString).replace(/\D/g, '');
		var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
		if (match) return `(${match[1]})${match[2]}-${match[3]}`;
		return null;
	}

	angular
		.module('app.storelocator')
		.controller('LocationsCtrl', ['$scope', '$rootScope', '$window', 'appSettings', 'locations', 'markerService', 'spinner', '$timeout', '$http', 'branchLocatorService', 'googleTagManagerService', LocationsCtrl]);

	function LocationsCtrl($scope, $rootScope, $window, appSettings, locations, markerService, spinner, $timeout, $http, branchLocatorService, googleTagManagerService) {

		$scope.selectBranch = function (branch) {
			branchLocatorService.ChooseBranchByCode(branch.locationcode, function (response) {
				var branch = {
					branchState: response.data.context.BranchState,
					branchCity: response.data.context.BranchCity,
					branchCode: response.data.context.BranchCode
				};

				$rootScope.$broadcast('branchChanged', branch);
			});
		};

		function OrderByLocation(location1, location2) {
			if (location1.name > location2.name) return 1;
			if (location1.name < location2.name) return -1;
			return 0;
		}

		function OrderByDistance(location1, location2) {
			 return parseFloat(location1.distance) - parseFloat(location2.distance);
		}

		$scope.initCtrl = function (branchNo) {
			$scope.myLocationNo = branchNo;
		};
		
		function LoadLocations() {
			spinner.startLoad();
			$http.get(appSettings.getUrl('our-locations/locations', true))
				.then(function (response) {
					locations = response.data;
					locations.map(i => {i.phone = formatPhoneNumber(i.phone)});
					spinner.progress();
					Init();
				})
				.finally(spinner.endLoad);
		}

		function Init() {
			$scope.locations = locations.sort(OrderByLocation) || [];
			for (var i = 0; i < $scope.locations.length; i++) {
				try {
					var location = $scope.locations[i];

					if (location.externalBrandDetails && location.externalBrandDetails.Icon) {
						location.icon = {
							url: location.externalBrandDetails.Icon,
						};
					} else {
						location.icon = {
							url: '//res.cloudinary.com/bedrosians/image/upload/assets/content/icons/location_icon.svg',
						};
					}


					if (!location.schedule) {
						location.openUntil = "";
						continue;
					}

					var locationZone = location.timezone;
					var dateInBranch = moment(moment.tz(moment(), locationZone).format("YYYY-MM-DD HH:mm:ss"));

					var weekDay = moment().format('dddd');
					var daySchedule = location.schedule[weekDay];

					var date = moment().format('YYYY-MM-DD');
					var begin = moment(date + ' ' + daySchedule.Begin, "YYYY-MM-DD HH:mm:ss");
					var end = moment(date + ' ' + daySchedule.End, "YYYY-MM-DD HH:mm:ss");
					var beginStr = daySchedule.Begin.substring(0, daySchedule.Begin.length - 3);

					if (daySchedule.Begin && dateInBranch > moment(begin) && moment(dateInBranch) < end) {
						location.openUntil = "Open Until " + daySchedule.End.substring(0, daySchedule.Begin.length - 3);
						continue;
					} else if (dateInBranch < moment(begin)) {
						var beginStr = daySchedule.Begin.substring(0, daySchedule.Begin.length - 3);
						location.openUntil = "Closed, will be open today, {time}".replace('{time}', beginStr);
						continue;
					} else {
						for (var k = 1; k < 6; k++) {
							var day = moment().add(k, 'days').format('dddd');
							if (location.schedule[day].Begin) {
								location.openUntil = "Closed, will be open on {day}, {time}".replace('{day}', day).replace('{time}', beginStr);
								break;
							}
						}
					}
				} catch (err) {
					console.error(err);
				}
			}
			$scope.filteredLocations = $scope.locations;
			$scope.nearestLocationsCount = 0;
			$scope.selectedLocation = null;
			$scope.userEnteredLocation = null;
			$scope.findLocation = findLocation;
			$scope.lastSearchResultQuery = '';
			$scope.clearSearch = clearSearch;
			$scope.query = '';
			$scope.isInitialized = false;
			/* This will be overrided by fit="'true'" */
			$scope.map = {
				center: { latitude: 40.1451, longitude: -99.6680 },
				zoom: 4,
				bounds: {}
			};
			$scope.mapControl = {};

			$scope.options = {
				disableDefaultUI: true,
				maxZoom: 8,
				minZoom: 3
			};
			$scope.markerOptions = {};
			$scope.windowOptions = { visible: true, boxClass: "marker-info-window-outer" };
			$scope.zoomIn = zoomIn;
			$scope.zoomOut = zoomOut;
			$scope.markerClick = markerClick;

			$scope.markerClose = function () { $scope.selectedLocation = null; };
			$scope.showLocation = function (location) { goToLocation(location, true); };

			spinner.progress();

			markerService.initMarkers($scope.markerOptions)
				.then(function () {
					$scope.isInitialized = true;
					spinner.endLoad();
				});
		}

		$scope.getCurrentPosition = function () {
			
			if (navigator.geolocation) {
				navigator.geolocation.getCurrentPosition(function (pos) {
					var myPosition = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
					computeDistanceBetweenLocations(myPosition);
				}, function (error) {
					
				});
			}
		};


		//http://jeffjason.com/2011/12/google-maps-radius-to-zoom/
		function radiusToZoom(radius) {
			return Math.round(14 - Math.log(radius) / Math.LN2); //zoom level 14 is a 1 mile radius search
		}

		var defaultZoomRadius = radiusToZoom(100); // set radius in 100 miles

		$scope.changeLocation = function (location) {
			var url = appSettings.getUrl("shipping/changeLocation/", true);
			$http.post(url, { id: location.locationcode })
				.success(function () {
					$scope.myLocationNo = location.locationcode;
				});
		};

		$scope.goto = function (url) {
			$window.location.href = url;
		};

		function goToLocation(location, toCenter) {
			$scope.selectedLocation = location;
			var toZoom = $scope.map.zoom < 10;

			if (toZoom) {
				$scope.map.zoom = 10;
			}

			if (toZoom || toCenter) {
				$scope.map.center = {
					latitude: location.latitude,
					longitude: location.longitude
				};
			}
		}

		function zoomIn() {
			$scope.map.zoom = $scope.map.zoom + 1;
		}

		function zoomOut() {
			/* Part of the world size */
			if ($scope.map.zoom > 3) {
				$scope.map.zoom = $scope.map.zoom - 1;
			}
		}

		function setZoomWithFitBounds() {
			var bounds = new google.maps.LatLngBounds();
			$.map($scope.filteredLocations, function (loc) {
				var boundsPoints = [];
				var locationCoords = new google.maps.LatLng(loc.latitude, loc.longitude);
				boundsPoints.push(locationCoords);

				for (var i = 0; i < boundsPoints.length; i++) {
					bounds.extend(boundsPoints[i]);
				}
			});
			$scope.gmap = $scope.mapControl.getGMap();
			$scope.gmap.fitBounds(bounds);
		}

		function markerClick(a, b, marker, d) {
			var w = $window.outerWidth;
			//if mobile, redirect to landing page
			if (w < 768) {
				$window.location.href = marker.branchaddressurl;
			} else {
				goToLocation(marker);
			}
		}


		function computeDistanceBetweenLocations(location) {

			$scope.nearestLocationsCount = 0;
			$scope.gmap = $scope.mapControl.getGMap();

			var userCoords = new google.maps.LatLng(location.lat(), location.lng());
			var boundsPoints = [];
			$.map($scope.filteredLocations, function (loc) {
				var locationCoords = new google.maps.LatLng(loc.latitude, loc.longitude);
				loc.distance = parseFloat((google.maps.geometry.spherical.computeDistanceBetween(userCoords, locationCoords) * 0.000621371192).toFixed(2));
				// check if between current location and user entered location in a radius of 100 mi
				if (loc.distance <= 100) {
					$scope.nearestLocationsCount++;
					boundsPoints.push(locationCoords);
				}
			});

			if ($scope.nearestLocationsCount > 0) {
				var bounds = new google.maps.LatLngBounds();
				for (var i = 0; i < boundsPoints.length; i++) {
					bounds.extend(boundsPoints[i]);
				}
				$scope.gmap.fitBounds(bounds);

				google.maps.event.addListenerOnce($scope.gmap, "bounds_changed", function() {
					if ($scope.gmap.getZoom() > defaultZoomRadius) $scope.gmap.setZoom(defaultZoomRadius); // 100 miles
				});
			} else {
				setZoomWithFitBounds();
			}
			
			setTimeout(() => $scope.$digest(), 0);
		}

		$scope.setFilter = function (filter) {
			$scope.filter = filter;
			var l = [];
			for (var i = 0; i < $scope.locations.length; i++) {
				if (filter === '') {
					l.push($scope.locations[i]);
					continue;
				}
				for (var j = 0; j < $scope.locations[i].branchtype.length; j++) {
					if ($scope.locations[i].branchtype[j] === filter) {
						l.push($scope.locations[i]);
						continue;
					}
				}
			}
			$scope.filteredLocations = l;

			//setZoomWithFitBounds();
		};

		function clearSearch() {
			$scope.userEnteredLocation = null;
			$scope.query = '';

			$scope.locations = locations.sort(OrderByLocation) || [];
			setZoomWithFitBounds();
		}

		function findLocation(query) {
			if (!query) {
				return;
			}
			spinner.startLoad();

			var geocoder = new google.maps.Geocoder();
			geocoder.geocode({ "address": query }, function (results, status) {
				if (status === google.maps.GeocoderStatus.OK && results.length > 0) {
					$scope.$apply(function () {
						$scope.userEnteredLocation = results[0].geometry.location;
						console.log("Lo que hay en location: ",results[0].geometry.location);
						spinner.progress();

						computeDistanceBetweenLocations($scope.userEnteredLocation);

						$scope.locations = $scope.locations.sort(OrderByDistance);
						let location = $scope.locations?.length > 0 ? $scope.locations[0].name : null;

						googleTagManagerService.LocationSearchEvent(query, location, $scope.nearestLocationsCount/*$scope.locations.map(x => x.name).join(', ')*/);
					});

					$scope.lastSearchResultQuery = query;					
					
					angular.element("#locations-container")[0].scrollTop = 0;
					$window.scrollTo(0, angular.element('#locations-container').offsetTop);

					spinner.endLoad();

				} else {
					$scope.$apply(function () {
						$scope.userEnteredLocation = null;
						setZoomWithFitBounds();
						googleTagManagerService.LocationSearchEvent(query, null, $scope.nearestLocationsCount);
					});
					spinner.endLoad();
				}
			});
		}

		// init map and markers
		LoadLocations();
	}
}());
;
(function () {
	'use strict';

	angular
		.module('app.storelocator')
		.factory('markerService', markerService);

	//	oep.utils.appSettings
	markerService.$inject = ['appSettings', 'uiGmapGoogleMapApi'];

	function markerService(appSettings, uiGmapGoogleMapApi) {
		return {
			initMarkers: initMarkers
		};

		function initMarkers(options) {
			return uiGmapGoogleMapApi.then(function(gmaps) {
				//options.icon = {
				//	url: '//res.cloudinary.com/bedrosians/image/upload/assets/content/icons/location_icon.svg',
				//	size: new gmaps.Size(66, 103, 'px', 'px'),
				//	scaledSize: new gmaps.Size(33, 51.5, 'px', 'px'),
				//	origin: new gmaps.Point(0, 0),
				//	anchor: new gmaps.Point(12.5, 51)
				//}
				options.animation = gmaps.Animation.DROP;
			});
		}
	}
}());;
(function () {
	'use strict';
	
	function oepTag($window, appSettings, userTagsService, myModuleConst, googleTagManagerService) {
		return {
			replace: true,
			restrict: 'E',
			scope: {
				isAuth: '=',
				tagItem: '=',
			},
			templateUrl: appSettings.getUrl(myModuleConst.oepTagTemplatePath, false),
			link: function (scope, element, attrs) {
				scope.showAddTag = false;
				
				scope.toggleAddTag = function () {
					scope.showAddTag = !scope.showAddTag;
					scope.clearAlertMessage();
					scope.clearAddTagName();
				}
				
				scope.showAddTagSection = function () {
					scope.showAddTag = true;
				}
				
				scope.hideAddTagSection = function () {
					scope.showAddTag = false;
				}
				
				scope.addNewTag = function () {
					let name = scope.model.addTagName.trim();
					
					if (!name) {
						scope.model.alertMessage = 'Project name is required!';
						return;
					}
					
					const checkTagName = (tag) => tag.Name.trim().toUpperCase()
						=== name.toUpperCase();
					
					if (scope.model.userTags.some(checkTagName)) {
						scope.model.alertMessage = 'Project with same name already exists!';
						return;
					}
					
					scope.waiting = true;
					
					userTagsService.AddNewUserTag({ name }).then((tag) => {
						tag.Checked = true;
						scope.model.userTags.push(tag);
						scope.toggleAddTag();
					}).finally(() => {
						scope.waiting = false;
					});
				}
				
				scope.clearAddTagName = function () {
					scope.model.addTagName = null;
				}
				
				scope.clearAlertMessage = function () {
					scope.model.alertMessage = null;
				}
				
				scope.tagTemplateUrl = appSettings.getUrl(myModuleConst.partialUserTagsPath, false);
				scope.waiting = false;
				scope.title = 'Add this product to an Ideabook';
				scope.templateId = 'UserTagsModalDialog.html';
				
				scope.note = '';
				
				scope.GetUserTagEntryMappings = getUserTagEntryMappings;
				scope.SetUserTagEntryMappings = setUserTagEntryMappings;
				scope.Close = closeDialog;
				
				scope.$watch('tagItem.ProductCode', function (value) {
					checkAssignedTags();
				});
				
				function resetModel() {
					scope.model = {
						userTags: [],
						addTagName: '',
						note: '',
						alertMessage: '',
						firstlyCheckedTags: []
					}
				}
				
				function closeDialog() {
					userTagsService.Close();
					scope.toggleAddTag();
				}
				
				function checkAssignedTags() {
					if(!scope.isAuth) return;
					scope.hasAssignedTags = false;
					userTagsService.CheckAssignedTags({ itemNo: scope.tagItem.ProductCode })
						.then((result) => scope.hasAssignedTags = result.data);
				}
				
				function validateUserTag() {
					if (scope.model.addTagName) {
						scope.model.alertMessage = '';
						var filter = $.grep(scope.model.userTags, function (tag) {
							if (tag.Name.trim().toUpperCase() === scope.model.addTagName.trim().toUpperCase()) {
								return true;
							}
						});
						if (filter.length === 0) {
							return true;
						} else {
							scope.model.alertMessage = 'Project with same name already exists!';
							return false;
						}
					}
					return true;
				}
				
				function getUserTagEntryMappings() {
					resetModel();
					scope.waiting = true;
					userTagsService.GetUserTagEntryMappings(scope, scope.templateId, { itemNo: scope.tagItem.ProductCode }).then(function (userTags) {
						scope.model.userTags = userTags;
						$.map(scope.model.userTags, function (m) {
							m.DateCreated = new Date(parseInt(m.DateCreated.substr(6)));// with parse.int for Date, because JsonResult deserialization
						});
						scope.model.firstlyCheckedTags = $.map(scope.model.userTags, function (n) {
							if (n.Checked) {
								return n.Id;
							}
						});
						scope.waiting = false;
						console.log(scope.model);
					}, function (error) {
						scope.waiting = false;
						console.log(error);
						//$window.alert(error);
					});
				}
				
				function setUserTagEntryMappings() {
					
					//if (!validateUserTag()) {
					//	return false;
					//}
					
					scope.waiting = true;

					let product = scope.tagItem;

					let productModel = {
						Size: product.Size,
						Note: scope.model.note,
						ProductId: product.ProductId,
						ProductCode: product.ProductCode,
						Description: product.Description,
						SeriesColor: product.SeriesColor,
						ProductSeries: product.ProductSeries,
						Url: window.location.origin + appSettings.getUrl("product/detail/" + product.UrlFriendlyStyleName + "?itemNo=" + product.ProductCode, true),
						ImageUrl: "https://res.cloudinary.com/bedrosians/image/upload/t_product_150/v1/cdn-bedrosian/assets/products/hiresimages/" + product.ImageName,
					}
					
					let params = {
						firstlyCheckedTags: scope.model.firstlyCheckedTags,
						userTagEntries: scope.model.userTags,
						productModel: productModel,
					}
					
					userTagsService.SetUserTagEntryMappings(params).then(function (data) {
						if (data) {
							
							googleTagManagerService.AddToFavoritesEvent(scope.tagItem);
							
							scope.model.firstlyCheckedTags = $.map(scope.model.userTags, function (n) {
								if (n.Checked) {
									return n.Id;
								}
							});
							
							scope.hasAssignedTags = $.grep(scope.model.userTags, function (tag) {
								if (tag.Checked) {
									return true;
								}
								return false;
							}).length > 0;
						}
					}, function (error) {
						scope.waiting = false;
						$window.alert(error);
						console.log(error);
					}).finally(() => {
						scope.waiting = false;
						closeDialog();
					});
				}
			}
		}
	}
	
	window.bdApp.directive('oepTag', ['$window', 'appSettings', 'userTagsService', 'myModuleConst', 'googleTagManagerService', oepTag]);
}());
;
(function () {
	'use strict';
	
	function UserProfileTagsCtrl($scope, ngDialog, userProfileTags, userProfileTagsService, userTagsService) {
		$scope.newTag = {Id: -1, Name: null};
		
		$scope.userProfileTags = $.map(userProfileTags, convertTagDate);
		
		function findSameNameTag(tag) {
			return $scope.userProfileTags
				.find(x => x.Id !== tag.Id && x.Name.trim().toUpperCase() === tag.Name.trim().toUpperCase());
		}
		
		function tagNameExists(tag) {
			let existsTag = findSameNameTag(tag);
			if(!existsTag) return false;
			setTimeout(() => alert('Project with same name already exists!'), 0);
			return existsTag;
		}
		
		function convertTagDate(tag) {
			return (tag.DateCreated = new Date(tag.DateCreated), tag);
		}
		
		$scope.addNewTag = function (form) {
			if(form.$invalid || tagNameExists($scope.newTag)) return;
			
			$scope.busy = true;
			
			userTagsService.AddNewUserTag($scope.newTag).then(res => {
				$scope.userProfileTags.push(convertTagDate(res))
				$scope.newTag.Name = null;
				$scope.busy = false;
			});
		}
		
		$scope.editOrSaveTag = function (tag) {
			if(!tag.IsEdit) { tag.IsEdit = true; return; }
			if(tagNameExists(tag)) return;
			tag.IsEdit = false;
			userProfileTagsService.EditTag({model: tag});
		}
		
		$scope.removeTagPopup = function (tag) {
			$scope.tag = tag;
			ngDialog.open({
				scope: $scope,
				template: 'delete-tag',
				className: 'ngdialog-theme-plain delete-tag',
			});
		}
		
		$scope.removeTag = function (tag) {
			$scope.busy = true;
			userProfileTagsService.DeleteTag({model: tag}).then(res => {
				let index = $scope.userProfileTags.findIndex(x => x.Id === tag.Id);
				$scope.userProfileTags.splice(index, 1);
				$scope.busy = false;
			});
		}
		
		$scope.removeTagEntryPopup = function (entry, tag) {
			$scope.entry = entry;
			$scope.tag = tag;
			ngDialog.open({
				scope: $scope,
				template: 'delete-tag-entry',
				className: 'ngdialog-theme-plain delete-tag',
			});
		}
		
		$scope.removeTagEntry = function (entry, tag) {
			let params = {entryId: entry.EntryId, model: tag};
			userProfileTagsService.DeleteTagEntry(params).then(function (tag) {
				$scope.userProfileTags = $scope.userProfileTags.map((_tag) => {
					if(tag.Id === _tag.Id) _tag.TagEntryModels = _tag.TagEntryModels.filter(x => x.EntryId != entry.EntryId);
					return _tag;
				})
			})
		}
		
		// function checkTagName(tag) {
		// 	let _tag = findSameNameTag(tag.Name);
		// 	if(!_tag) alert('Project with same name already exists!');
		// 	return !!_tag;
		// }
		
		// $scope.Init = function () {
		// 	$scope.waiting = false;
		// 	$scope.showInputText = false;
		// 	$scope.userProfileTags = userProfileTags;
		// 	$.map($scope.userProfileTags, function (m) {
		// 		m.DateCreated = new Date(m.DateCreated); // without parse.int for Date, because using IHtmlString deserialization
		// 	});
		// }
		
		// $scope.AddNewTag = function () {
		// 	$scope.newTagMode = true;
		// 	$scope.newTag = { Id: -1, Name: '' };
		// }
		
		// $scope.CancelNewTagName = function () {
		// 	$scope.newTagMode = false;
		// }
		
		// $scope.EditTag = function (tag) {
		// 	$('#read-' + tag.Id)[0].style.display = 'none';
		// 	$('#remove-' + tag.Id)[0].style.display = 'none';
		// 	$('#edit-' + tag.Id)[0].style.display = 'none';
		// 	$('#write-' + tag.Id)[0].style.display = 'initial';
		// 	$('#save-' + tag.Id)[0].style.display = 'initial';
		// 	$('#cancel-' + tag.Id)[0].style.display = 'initial';
		// 	$('#write-' + tag.Id)[0].alt = tag.Name;
		// };
		
		// $scope.ChangeTagName = function (tag) {
		// 	if(tagNameExists(tag.Name));
		// 	// let _tag = findSameNameTag(tag.Name);
		// 	//
		// 	// if(_tag) {
		// 	// 	alert('Project with same name already exists!');
		// 	// 	return;
		// 	// }
		//	
		//	
		//	
		// 	// if (tag.Name) {
		// 	// 	$scope.waiting = true;
		// 	// 	var params = {};
		// 	// 	if (tag.Id > 0) {
		// 	// 		var filter = $.grep($scope.userProfileTags, function (t) {
		// 	// 			if (t.Id !== tag.Id && t.Name.trim().toUpperCase() === tag.Name.trim().toUpperCase()) {
		// 	// 				return true;
		// 	// 			}
		// 	// 			return false;
		// 	// 		});
		// 	// 		if (filter.length === 0) {
		// 	// 			params = { model: tag };
		// 	// 			userProfileTagsService.EditTag(params).then(function (tag) {
		// 	// 				$('#read-' + tag.Id)[0].style.display = 'initial';
		// 	// 				$('#remove-' + tag.Id)[0].style.display = 'initial';
		// 	// 				$('#edit-' + tag.Id)[0].style.display = 'initial';
		// 	// 				$('#save-' + tag.Id)[0].style.display = 'none';
		// 	// 				$('#write-' + tag.Id)[0].style.display = 'none';
		// 	// 				$('#cancel-' + tag.Id)[0].style.display = 'none';
		// 	// 				$scope.waiting = false;
		// 	// 			}, function (error) {
		// 	// 				$scope.waiting = false;
		// 	// 				console.log(error);
		// 	// 			});
		// 	// 		} else {
		// 	// 			$scope.waiting = false;
		// 	// 			alert('Project with same name already exists!');
		// 	// 		}
		// 	// 	} else {
		// 	// 		params = { name: tag.Name };
		// 	// 		userTagsService.AddNewUserTag(params).then(function (tag) {
		// 	// 			$scope.userProfileTags.push(tag);
		// 	// 			$scope.newTagMode = false;
		// 	// 			$scope.waiting = false;
		// 	// 		}, function (error) {
		// 	// 			$scope.waiting = false;
		// 	// 			console.log(error);
		// 	// 		});
		// 	// 	}
		// 	// }
		// }
		
		// $scope.CancelChangeTagName = function (tag) {
		// 	$('#read-' + tag.Id)[0].style.display = 'initial';
		// 	$('#remove-' + tag.Id)[0].style.display = 'initial';
		// 	$('#edit-' + tag.Id)[0].style.display = 'initial';
		// 	$('#write-' + tag.Id)[0].style.display = 'none';
		// 	$('#cancel-' + tag.Id)[0].style.display = 'none';
		// 	$('#save-' + tag.Id)[0].style.display = 'none';
		// 	tag.Name = $('#write-' + tag.Id)[0].alt;
		// }
		
		// $scope.EditEntry = function (entryId, tag) {
		// 	var params = { entryId: entryId, model: tag };
		// 	userProfileTagsService.EditEntry(params);
		// }
		
		//
		// $scope.DeleteTagEntryPopUp = function (entry, tag) {
		// 	$scope.entries = entry;
		// 	$scope.tags = tag;
		// 	ngDialog.open({
		// 		template: '/delete-tag-entry.html',
		// 		className: 'ngdialog-theme-plain delete-tag',
		// 		scope: $scope
		// 	});
		// }
		//
		//
		// $scope.DeleteTagEntry = function (entryId, tag, confirmDelete) {
		// 	if (confirmDelete) {
		// 		$scope.waiting = true;
		// 		var params = { entryId: entryId, model: tag };
		// 		userProfileTagsService.DeleteTagEntry(params).then(function (tag) {
		// 			$scope.userProfileTags = $scope.userProfileTags.map((_tag) => {
		// 				if (tag.Id != _tag.Id) return _tag;
		// 				_tag.TagEntryModels = _tag.TagEntryModels.filter(x => x.EntryId != entryId);
		// 				return _tag;
		// 			});
		//			
		// 			$scope.waiting = false;
		//			
		// 		}, function (error) {
		// 			$scope.waiting = false;
		// 			console.log(error);
		// 		});
		// 		return true;
		// 	}
		// 	return false;
		// }
		
		// $scope.Init();
	}
	
	window.bdApp.controller('UserProfileTagsCtrl', UserProfileTagsCtrl)
		.filter('unsafe', function ($sce) {
			return function (val) {
				return $sce.trustAsHtml(val);
			};
		});
})();
;
(function () {
	'use strict';
	
	function userProfileTagsService(appSettings, $http, $q) {
		
		function DeleteTag(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/DeleteTag", true),
				method: 'POST',
				data: params,
				dataType: "json"
			}).success(function (data) {
					if (data) {
						def.resolve(data);
					} else {
						def.reject("Failed to remove tag!");
					}
				})
				.error(function () {
					def.reject("Failed to remove tag!");
				});
			return def.promise;
		}
		
		function EditTag(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/EditTag", true),
				method: 'POST',
				data: params,
				dataType: "json"
			}).success(function (data) {
					if (data) {
						def.resolve(data);
					} else {
						def.reject("Failed to edit tag name!");
					}
				})
				.error(function () {
					def.reject("Failed to edit tag name!");
				});
			return def.promise;
		}
		
		function DeleteTagEntry(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/DeleteTagEntry", true),
				method: 'POST',
				data: params,
				dataType: "json"
			}).success(function (data) {
					if (data) {
						def.resolve(data);
					} else {
						def.reject("Failed to remove entry!");
					}
				})
				.error(function () {
					def.reject("Failed to remove entry!");
				});
			return def.promise;
		}
		
		function EditEntry(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/EditEntry", true),
				method: 'POST',
				data: params,
				dataType: "json"
			}).success(function (data) {
					if (data) {
						def.resolve(data);
					} else {
						def.reject("Failed to edit entry description!");
					}
				})
				.error(function () {
					def.reject("Failed to edit entry description!");
				});
			return def.promise;
		}
		
		return {
			EditTag: EditTag,
			EditEntry: EditEntry,
			DeleteTag: DeleteTag,
			DeleteTagEntry: DeleteTagEntry,
		}
	}
	
	angular.module('app')
		.service('userProfileTagsService', ['appSettings', '$http', '$q', userProfileTagsService]);
})();;
(function () {
	'use strict';

	function userTagsService(appSettings, $http, $q, ngDialog) {

		function CheckAssignedTags(params) {
			return $http({
				url: appSettings.getUrl("Tag/CheckAssignedTags", true),
				method: 'POST',
				params: params
			});
		}

		function AddNewUserTag(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/AddNewUserTag", true),
				method: 'POST',
				data: params,
				dataType: "json"
			}).success(function (data) {
				if (data) {
					def.resolve(data);
				} else {
					def.reject("Failed to add new tag!");
				}
			})
            .error(function () {
            	ngDialog.open({
            		template: '<div class="col-sm-12"><h4><strong>Warning</strong></h4></div><div class="ngdialog-message"> \
						  An error occurred while sending your request for adding new tag. Please try again.</div>',
            		className: 'ngdialog-theme-plain',
            		plain: 'true'
            	});
            	def.reject("An error occurred while sending your enquiry. Please try again or contact an administrator.");
            });
			return def.promise;
		}

		function GetUserTagEntryMappings(scope, templateId, params) {
			let def = $q.defer();
			
			ngDialog.open({
				scope: scope,
				closeByEscape: true,
				template: templateId,
				closeByDocument: true,
				className: 'ngdialog-theme-plain ideabook-add-dialog',
			});

			$http({
				method: 'GET',
				params: params,
				dataType: "json",
				url: appSettings.getUrl("Tag/GetUserTagEntryMappings", true),
			}).success(function (data) {
				def.resolve(data);
			}).error(function () {
				ngDialog.open({
					template: '<div class="col-sm-12"><h4><strong>Warning</strong></h4></div><div class="ngdialog-message"> \
						  An error occurred while sending your request for getting tags. Please try again.</div>',
					className: 'ngdialog-theme-plain',
					plain: 'true'
				});
				def.reject("An error occurred while sending your enquiry. Please try again or contact an administrator.");
			});
			return def.promise;
		}

		function SetUserTagEntryMappings(params) {
			var def = $q.defer();
			$http({
				url: appSettings.getUrl("Tag/SetUserTagEntryMappings", true),
				method: 'POST',
				dataType: "json",
				data: params
			}).success(function (data) {
				//ngDialog.close(); // close when done successfully.
				def.resolve(data);
			})
            .error(function () {
            	ngDialog.open({
            		template: '<div class="col-sm-12"><h4><strong>Warning</strong></h4></div><div class="ngdialog-message"> \
						  An error occurred while sending your request for saving changes. Please try again.</div>',
            		className: 'ngdialog-theme-plain',
            		plain: 'true'
            	});
            	def.reject("An error occurred while sending your enquiry. Please try again or contact an administrator.");
            });
			return def.promise;
		}

		function Close() {
			ngDialog.close();
		}

		return {
			Close: Close,
			AddNewUserTag: AddNewUserTag,
			CheckAssignedTags: CheckAssignedTags,
			GetUserTagEntryMappings: GetUserTagEntryMappings,
			SetUserTagEntryMappings: SetUserTagEntryMappings
		}
	}

	angular.module('app')
			   .service('userTagsService', ['appSettings', '$http', '$q', 'ngDialog', userTagsService]);
})();
;
(function () {
	'use strict';

	angular
		.module('app')
		.controller('WishListCtrl', ['$scope', '$http', '$window', 'appSettings', 'spinner', 'wishlist', 'ngDialog', 'appUtils', 'UomConversionService', WishListCtrl]);

	function WishListCtrl($scope, $http, $window, appSettings, spinner, wishlist, ngDialog, appUtils, UomConversionService) {
		//	having a state is bad practice, bad currenlty it's the only way to proceed.
		$scope.wishlist = wishlist;
		$scope.currentWishListName = "";
		$scope.currentWishListId = null;

		$scope.updateName = updateName;
		$scope.submitName = submitName;
		$scope.moveAllToCart = moveAllToCart;
		$scope.deteleWishlist = deteleWishlist;
		$scope.getProductImage = getProductImage;
		$scope.removeProduct = removeProduct;
		$scope.moveToCart = moveToCart;
		$scope.reloadPage = reloadPage;
		$scope.busy = false;
		$scope.updateShoppingBag = updateShoppingBag;
		$scope.updateQty = updateQty;
		$scope.init = init;
		$scope.resetRecentOpenedBagId = resetRecentOpenedBagId;
		$scope.setRecentOpenedBagId = setRecentOpenedBagId;
		$scope.hasUpdates = false;
		$scope.navigateToItem = navigateToItem;

		$scope.getShoppingBagItemMenu = getShoppingBagItemMenu;
		$scope.openMoreMenu = openMoreMenu;

		function getShoppingBagItemMenu(element) {
			return element.parentElement.parentElement.querySelector('.js-dropdown');
		}

		function openMoreMenu(element) {
			var activeMenu = getShoppingBagItemMenu(element.target);
			var offset = $(element.target).position();
			var leftValue = $(window).width() > 1300 ? offset.left : offset.left - 80;
			$(activeMenu).css('top', offset.top).css('left', leftValue).css('display', 'inline-block').css('position', 'absolute').css('width', '120px');
		}

		function navigateToItem(prod, open) {

			if (prod.Sku.IsHidden) {
				return null;
			}

			var url = appSettings.getUrl('product/detail/' + prod.UrlFriendlyName + '/?itemNo=' + prod.Sku.ProductCode, true);
			if (open) {
				$window.open(url, '_blank');
			} else {
				return url;
			}
		}

		function resetRecentOpenedBagId(wishListId) {
			localStorage.removeItem(wishListId);
		}

		function setRecentOpenedBagId(wishListId) {
			localStorage.setItem(wishListId, wishListId);
		}

		function init() {
			if (Array.isArray($scope.wishlist) && $scope.wishlist.length > 0) {
				$.map($scope.wishlist,
					function (t) {
						if (localStorage.getItem(t.QuoteId)) {
							t.isVisible = true;
						}
					});
			}
		}

		function checkUpdates() {
			$.map($scope.wishlist, function (t) {
				t.hasUpdates = 0;
				return $.map(t.Items, function (y) {
					if (y.Item.Qty && y.Item.Qty > 0 && parseFloat(y.Item.Qty) !== y.Item.resetValue) {
						t.hasUpdates++;
					}
				});
			});
		}

		function updateQty(prod) {
			if (!prod.Item.Qty || prod.Item.Qty > 99999) {
				$window.alert('Incorrect item qty. Qty must be greater than zero and less than 100000.');
				return false;
			}
			spinner.startLoad();
			$scope.busy = true;
			var url = appSettings.getUrl('en/WishList/UpdateItem');
			var qty = parseFloat(prod.Item.Qty);

			qty = UomConversionService.adjustSellQtyToSolidBaseUnitQty(qty, prod.Item.SellingUom);

			var model = {
				wishlistId: prod.WishListId,
				shoppingBagItemId: prod.Item.Id,
				qty: qty
			};

			$http({
				method: 'POST',
				url: url,
				data: model
			}).then(function successCallback(response) {
				prod.Item.Qty = prod.Item.resetValue = response.data.Qty;
				prod.Item.HandlingQty = response.data.HandlingQty;
				prod.Item.TotalAmount = response.data.TotalAmount;
				prod.Item.SaveAmount = response.data.SaveAmount;
				prod.Item.LeadTime = response.data.LeadTime;
				prod.Item.Warning = response.data.Warning;
				checkUpdates();
			}, function errorCallback(response) {
				$window.alert(response.statusText);
			}).finally(function () {
				$scope.busy = false;
				spinner.endLoad();
			});
		}

		function updateShoppingBag(wishList) {
			$scope.busy = true;
			spinner.startLoad();

			var itemsToUpdate = $.grep(wishList.Items, function (t) {
				return t.Item.Qty && parseFloat(t.Item.Qty) > 0;
			});

			if (itemsToUpdate.length !== wishList.Items.length) {
				$window.alert('Detected incorrect items. Please make sure all qty fields are filled and correct.');
				return false;
			}

			var queueForUpdate = $.grep(wishList.Items, function (t) {
				return parseFloat(t.Item.Qty) !== t.Item.resetValue;
			});


			var url = '', model = {};

			if (queueForUpdate.length === 1) {
				url = appSettings.getUrl('en/WishList/UpdateItem');
				model = {
					wishlistId: queueForUpdate[0].WishListId,
					shoppingBagItemId: queueForUpdate[0].Item.Id,
					qty: parseFloat(queueForUpdate[0].Item.Qty)
				};
				$http({
					method: 'POST',
					url: url,
					data: model
				}).then(function successCallback(response) {
					for (var i = 0; i < queueForUpdate.length; i++) {
						var item = queueForUpdate[i].Item;
						item.Qty = item.resetValue = response.data.Qty;
						item.TotalAmount = response.data.TotalAmount;
						item.SaveAmount = response.data.SaveAmount;
					}
					checkUpdates();
				}, function errorCallback(response) {
					$window.alert(response.statusText);
				}).finally(function () {
					localStorage.setItem(wishList.Items[0].WishListId, wishList.Items[0].WishListId);
					$scope.busy = false;
					spinner.endLoad();
				});

			} else if (queueForUpdate.length > 1) {
				url = appSettings.getUrl('en/WishList/UpdateItems');
				var items = $.map(queueForUpdate, function (t) {
					return { Key: t.Item.Id, Value: parseFloat(t.Item.Qty) };
				});
				model = {
					WishListId: wishList.Items[0].WishListId,
					ShoppingBagItems: items
				};

				$http({
					method: 'POST',
					url: url,
					data: model
				}).then(function successCallback(response) {
					wishList.Items = response.data.Items;
					for (var i = 0; i < wishList.Items.length; i++) {
						wishList.Items[i].Item.resetValue = wishList.Items[i].Item.Qty;
						$('#update-' + wishList.Items[i].Item.Id)[0].style.display = 'none';
						$('#reset-' + wishList.Items[i].Item.Id)[0].style.display = 'none';
					}
					checkUpdates();
				}, function errorCallback(response) {
					$window.alert(response.statusText);
				}).finally(function () {
					localStorage.setItem(wishList.Items[0].WishListId, wishList.Items[0].WishListId);
					$scope.busy = false;
					spinner.endLoad();
				});
			}
		}

		function reloadPage() {
			$window.location.reload();
		}

		function getProductImage(prod) {
			if (prod) {
				return "//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/" + prod.Sku.Image + ".jpg";
			}
			return '';
		}

		function removeProduct(prod) {
			spinner.startLoad();

			var url = appSettings.getUrl('en/WishList/RemoveItem');
			var model = {
				wishlistId: prod.WishListId,
				shoppingBagItemId: prod.Item.Id
			};
			$http.post(url, model).then(function successCallback(response) {
				$window.location.reload();
			}, function errorCallback(response) {
				$window.alert(response.statusText);
			}).finally(spinner.endLoad);
		}

		function moveToCart(prod) {
			$scope.busy = true;
			spinner.startLoad();

			var url = appSettings.getUrl('en/WishList/AddItemToOrder');
			var model = {
				wishlistId: prod.WishListId,
				shoppingBagItemId: prod.Item.Id
			};
			$http.post(url, model).then(function successCallback(response) {
				$scope.message = 'This product has been succesfully added to your shopping cart';
				ngDialog.open({
					template: '/shopping-bag-item-moved.html',
					className: 'ngdialog-theme-plain shopping-bag-item-moved-dialog',
					showClose: false,
					scope: $scope,
					preCloseCallback: function () {
						$scope.busy = false;
						reloadPage();
					}
				});
			}, function errorCallback(response) {
				$window.alert(response.statusText);
			}).finally(function () {
				localStorage.setItem(prod.WishListId, prod.WishListId);
				$scope.busy = false;
				spinner.endLoad();
			});
		}

		function updateName($event) {
			var node = $($event.target);
			$scope.currentWishListName = node.text();
			$scope.currentWishListId = node.data('wishlist');
		}

		function moveAllToCart(wishlistId) {
			spinner.startLoad();
			$scope.busy = true;
			var url = appSettings.getUrl('en/WishList/AddAllItemsToOrder');
			$http.post(url,
				{
					wishlistId: wishlistId
				})
				.then(function successCallback(response) {
					$scope.message = 'All products have been successfully added to your shopping cart';
					ngDialog.open({
						template: '/shopping-bag-item-moved.html',
						className: 'ngdialog-theme-plain shopping-bag-item-moved-dialog',
						scope: $scope,
						preCloseCallback: function () {
							$scope.busy = false;
							reloadPage();
						}
					});
				},
					function errorCallback(response) {
						$window.alert(response.statusText);
					})
				.finally(function () {
					$scope.busy = false;
					spinner.endLoad();
				});
		}

		function deteleWishlist(wishlistId) {
			ngDialog.openConfirm({
				template: '/confirm-remove-shopping-bag.html',
				className: 'ngdialog-theme-plain shopping-bag-item-moved-dialog',
			}).then(function (confirm) {
				spinner.startLoad();
				$scope.busy = true;
				var url = appSettings.getUrl('en/WishList/remove');
				$http.post(url, { wishlistId: wishlistId }).then(function successCallback(response) {
					$window.location.reload();
				}, function errorCallback(response) {
					$window.alert(response.statusText);
					spinner.endLoad();
					$scope.busy = false;
				});
			}, function (reject) {
			});
		}

		function submitName(name) {
			if (!name) {
				return "Please provide wish list name";
			}

			var url = appSettings.getUrl('wishlist/rename', true);
			var model = {
				wishlistId: $scope.currentWishListId,
				newWishListName: name
			};

			spinner.startLoad();
			return $http.post(url, model).then(function successCallback(response) {
				location.reload(true);
			}, function errorCallback(response) {
				$window.alert(response.statusText);
			}).finally(spinner.endLoad);
		}

		init();
	}
})();
;
(function () {
	'use strict';

	angular
		.module('app')
		.controller('WishListDialogCtrl', WishListDialogCtrl);

	WishListDialogCtrl.$inject = ['$scope', '$http', '$window', 'appSettings', 'spinner', 'ngDialog', 'wishlists', 'shoppingBagItems', '$filter', 'appUtils', 'UomConversionService', 'googleTagManagerService'];

	function WishListDialogCtrl($scope, $http, $window, appSettings, spinner, ngDialog, wishlists, shoppingBagItems, $filter, appUtils, UomConversionService, googleTagManagerService) {
		$scope.addToWishList = addToWishList;
		$scope.addToWishListDialog = addToWishListDialog;
		$scope.closeDialog = closeDialog;
		$scope.wishlists = wishlists || [];
		$scope.saveWishList = saveWishList;
		$scope.getProductImage = getProductImage;
		$scope.selectedWishlists = [];
		$scope.updateQty = updateQty;
		$scope.shoppingBagItems = shoppingBagItems;
		$scope.navigateToItem = navigateToItem;
		$scope.removeBagItem = removeBagItem;
		$scope.init = init;
		$scope.getShoppingBagItemMenu = getShoppingBagItemMenu;
		$scope.openMoreMenu = openMoreMenu;
		$scope.changeFulfillmentType = changeFulfillmentType;

		function reloadPage() {
			$window.location.reload();
		}

		function init(prodId) {
			const item = $.grep($scope.shoppingBagItems,
				function (t) {
					return t.Id === prodId;
				})[0];

			item.Options = item.Options.map(option => {
				option._NAME = (option.Type === 'Shipping') ? 'Delivery' : option.Type;
				return option;
			});

			return item;
		}

		function navigateToItem(item, open) {

			if (item.Sku.IsHidden) {
				return null;
			}

			var url = appSettings.getUrl('product/detail/' + item.UrlFriendlyName + '/?itemNo=' + item.Sku.ProductCode, true);
			if (open) {
				$window.open(url, '_blank');
			} else {
				return url;
			}
		}

		$scope.model = {
			selectedWishList: null,
			newWishListName: null
		};

		function updateQty(prod) {
			if (!prod.Qty || prod.Qty > 99999) {
				prod.Warning = 'Please enter a number between 1 and 99,999';
				return false;
			}
			spinner.startLoad();
			$scope.busy = true;

			var qty = parseFloat(prod.Qty);
			qty = UomConversionService.adjustSellQtyToSolidBaseUnitQty(qty, prod.SellingUom);

			prod.resetValue = qty;

			var itemsToUpdate = [];
			var model = {
				bagItemId: prod.Id,
				skuId: prod.Sku.Id,
				branchNo: prod.Branch ? prod.Branch.LocationCode : null,
				qty: qty
			};
			itemsToUpdate.push(model);

			var url = appSettings.getUrl('ShoppingBag/UpdateBagItems', true);
			$http({
				method: 'POST',
				url: url,
				data: itemsToUpdate
			}).then(function successCallback(response) {

				for (var i = 0; i < $scope.shoppingBagItems.length; i++) {
					var item = $scope.shoppingBagItems[i];
					item.resetValue = item.Qty;
				}
				reloadPage();
			}, function errorCallback(response) {
				$window.alert(response.statusText);
				$scope.busy = false;
				spinner.endLoad();
			});
		}

		function getProductImage() {
			return "//res.cloudinary.com/bedrosians/image/upload/t_product_150,f_auto/v1/cdn-bedrosian/assets/products/hiresimages/" + $scope.item.Sku.Image + ".jpg";
		}

		function addToWishListDialog() {
			ngDialog.open({
				template: 'addToWishListTemplate',
				className: 'ngdialog-theme-plain whish-list-add-dialog',
				controller: this,
				scope: $scope
			});
		}

		function closeDialog() {
			ngDialog.close();
		}

		function saveWishList() {
			if ($scope.newWishListName) {

				var filterResult = $filter('filter')($scope.wishlists, {
					Name: $scope.newWishListName
				});

				if (filterResult.length > 0) {
					$window.alert('Wishlist with such name already exists. Please choose another name.');
					return false;
				}
				spinner.startLoad();

				$http.post(appSettings.getUrl('WishList/AddWishList', true),
					{
						name: $scope.newWishListName,
						note: $scope.newWishListNote
					})
					.then(function successCallback(result) {
							if (result.data.Success) {
								result.data.Value.selected = true;
								$scope.wishlists.push(result.data.Value);
								// add item to a new wishlist
								addToWishList();
							} else {
								$scope.busy = false;
								spinner.endLoad();
								$window.alert(result.data.Messages[0]);
							}
						},
						function errorCallback(response) {
							$scope.busy = false;
							spinner.endLoad();
							$window.alert(response.statusText);
						});
			} else {
				addToWishList();
			}
		}

		function addToWishList() {
			var wishlistsIds = [];
			for (var i = 0; i < $scope.wishlists.length; i++) {
				if ($scope.wishlists[i].selected) {
					wishlistsIds.push($scope.wishlists[i].QuoteId);
				}
			}
			if (wishlistsIds.length > 0) {
				$scope.busy = true;
				var url = appSettings.getUrl('WishList/AddItemInMultipleWishlists', true);

				var model = {
					itemNo: $scope.item.Sku.ProductCode,
					qty: $scope.item.Qty,
					shoppingBagItemId: $scope.item.Id,
					wishListsIds: wishlistsIds,
					branchNo: $scope.item.Branch ? $scope.item.Branch.LocationCode : null
				};

				$http.post(url, model)
					.then(function successCallback(response) {
							closeDialog();
							$window.location.reload();
						},
						function errorCallback(response) {
							$scope.busy = false;
							spinner.endLoad();
							$window.alert(response.statusText);
							console.log('Error during adding to the wish list');
						});
			} else {
				if ($scope.wishlists.length > 0) {
					$window.alert('Choose an existing Shopping Bag or save to a New Shopping Bag.');
					return;
				} else if (!$scope.newWishListName) {
					$window.alert('Enter name for saving to a New Shopping Bag.');
					return;
				}
			}
		}

		function removeBagItem(bagItemId, skuId, itemNo, branchNo) {
			spinner.startLoad();
			$scope.busy = true;
			var url = appSettings.getUrl('ShoppingBag/Remove', true);

			var model = {
				shoppingBagItemId: bagItemId,
				branchNo: branchNo,
				skuId: skuId
			};

			$http.post(url, model)
				.then(function successCallback(response) {

						//Pushing data to Google Tag Manager Service:
						googleTagManagerService.ItemRemovedEvent(itemNo, true);

						$window.location.reload();
					},
					function errorCallback(response) {
						$scope.busy = false;
						$window.alert(response.statusText);
						console.log('Error during removing shopping bag item');
					})
				.finally(spinner.endLoad);
		}


		function getShoppingBagItemMenu(element) {
			return element.parentElement.parentElement.querySelector('.js-dropdown');
		}

		function openMoreMenu(element) {
			var activeMenu = getShoppingBagItemMenu(element.target);
			var offset = $(element.target).position();
			var leftValue = $(window).width() > 1300 ? offset.left : offset.left - 80;
			$(activeMenu).css('top', offset.top).css('left', leftValue).css('display', 'inline-block').css('position', 'absolute').css('width', '120px');

		}

		function changeFulfillmentType(item, option) {
			spinner.startLoad();

			$scope.busy = true;

			$http.post(appSettings.getUrl('ShoppingBag/ChangePickupStoreNumber/', true), {
				id: item.Id,
				to: option.BranchNo
			})
				.then(function (result) {
					console.log(result);
				})
				.finally(function () {
					$window.location.reload();
				});
		}

	}
})();
;
