diff --git a/DTDD.html b/DTDD.html new file mode 100644 index 0000000..ecb60d6 --- /dev/null +++ b/DTDD.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại iphone

+
+
+
+ +
+

iPhone 15 Pro Max 256GB | Chính hãng VN/A

+

Giá: 33.490.000đ

+
+ +
+
+
+
+ +
+

iPhone 14 Pro Max 128GB | Chính hãng VN/A

+

Giá: 27.090.000đ

+
+ +
+
+
+
+ +
+

iPhone 15 128GB | Chính hãng VN/A

+

Giá: 21.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

iPhone 14 128GB | Chính hãng VN/A

+

Giá: 18.490.000đ

+
+ +
+
+
+
+ +
+

iPhone 12 64GB | Chính hãng VN/A

+

Giá: 12.790.000đ

+
+ +
+
+
+
+ +
+

iPhone 13 Pro Max 128GB | Chính hãng VN/A

+

Giá: 22.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

iPhone 11 64GB | Chính hãng VN/A

+

Giá: 10.690.000đ

+
+ +
+
+
+
+ +
+

iPhone 14 Pro Max 256GB | Chính hãng VN/A

+

Giá: 29.590.000đ

+
+ +
+
+
+
+ +
+

iPhone 11 128GB | Chính hãng VN/A

+

Giá: 12.190.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/acer.html b/Laptop/acer.html new file mode 100644 index 0000000..baf1d26 --- /dev/null +++ b/Laptop/acer.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop acer

+
+
+
+ +
+

Laptop Acer Swift X SFX16-51G-516Q NX.AYKSV.002

+

Giá: 23.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop Acer Gaming Aspire 7 A715-76-57CY NH.QGESV.004

+

Giá: 13.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Gaming Acer Nitro 5 Eagle AN515-57-5669 NH.QEHSV.001

+

Giá: 16.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Acer Aspire 7 A715-76G-5806

+

Giá: 19.890.000đ

+
+ +
+
+
+
+ +
+

Laptop Acer Aspire 3 A315-56-38B1 NX.HS5SV.00G

+

Giá: 7.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Acer Aspire 5 A515-58GM-59LJ

+

Giá: 16.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Acer Swift 3 SF314-512-56QN NX.K0FSV.002

+

Giá: 14.890.000đ

+
+ +
+
+
+
+ +
+

Laptop Acer Aspire 3 A315-58-53S6 NX.AM0SV.005

+

Giá: 11.490.000đ

+
+ +
+
+
+
+ +
+

Laptop Acer Aspire 7 A715-76G-59MW

+

Giá: 17.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/apple.html b/Laptop/apple.html new file mode 100644 index 0000000..83e45eb --- /dev/null +++ b/Laptop/apple.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop macbook

+
+
+
+ +
+

Apple MacBook Air M1 256GB 2020

+

Giá: 19.090.000 đ

+
+ +
+
+
+
+ +
+

Apple Macbook Air M2 2022 8GB 256GB

+

Giá: 26.490.000đ

+
+ +
+
+
+
+ +
+

Macbook Air 15 inch M2 2023 8GB 256GB

+

Giá: 30.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Macbook Pro 14 M1 Pro 10 CPU - 16 GPU 16GB 1TB 2021

+

Giá: 43.990.000đ

+
+ +
+
+
+
+ +
+

Apple Macbook Pro 13 M2 2022 8GB 256GB

+

Giá: 29.890.000đ

+
+ +
+
+
+
+ +
+

MacBook Pro 14 inch M2 Pro 2023

+

Giá: 58.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Apple MacBook Pro 13 M2 2022 16GB 256GB

+

Giá: 35.390.000đ

+
+ +
+
+
+
+ +
+

MacBook Air 15 inch M2 2023 16GB 512GB

+

Giá: 41.490.000đ

+
+ +
+
+
+
+ +
+

MacBook Pro 16 inch M2 Pro 2023

+

Giá: 60.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/asus.html b/Laptop/asus.html new file mode 100644 index 0000000..c4009fd --- /dev/null +++ b/Laptop/asus.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop asus

+
+
+
+ +
+

Laptop Asus VivoBook Go 14 E1404FA-NK177W

+

Giá: 12.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop Asus TUF GAMING F15 FX506HF-HN014W

+

Giá: 16.890.000đ

+
+ +
+
+
+
+ +
+

Laptop Asus TUF Gaming F15 FX507ZC4-HN074W

+

Giá: 19.690.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop ASUS X515MA-BR481W

+

Giá: 6.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Asus VivoBook 14X OLED S3405VA-KM071W

+

Giá: 23.090.000đ

+
+ +
+
+
+
+ +
+

Laptop ASUS ZenBook UP5401ZA-KN005W

+

Giá: 19.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop ASUS ROG Flow X13 GV301RC-LJ050W

+

Giá: 29.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Asus ROG Strix G16 G614JU-N3135W

+

Giá: 33.890.000đ

+
+ +
+
+
+
+ +
+

Laptop ASUS Gaming TUF FX506LHB-HN188W

+

Giá: 14.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/dell.html b/Laptop/dell.html new file mode 100644 index 0000000..8b126cc --- /dev/null +++ b/Laptop/dell.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop dell

+
+
+
+ +
+

Laptop Dell Inspiron 14 Plus 7420 T9K26

+

Giá: 20.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop Dell Latidude 7320 9PPWV

+

Giá: 16.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Dell Vostro 3520

+

Giá: 17.490.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Dell Inspiron 15 3520 D5N53

+

Giá: 9.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Dell Inspiron 15 3525 NH20W

+

Giá: 16.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Dell Inspiron 7506-5903SLV

+

Giá: 18.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Dell Vostro 5620 V6I5001W1

+

Giá: 17.490.000đ

+
+ +
+
+
+
+ +
+

Laptop Dell Vostro 3405 V4R53500U003W

+

Giá: 15.490.000đ

+
+ +
+
+
+
+ +
+

Laptop Dell Vostro 14 3400 YX51W3

+

Giá: 17.490.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/gigabyte.html b/Laptop/gigabyte.html new file mode 100644 index 0000000..9c66b3d --- /dev/null +++ b/Laptop/gigabyte.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop gigabyte

+
+
+
+ +
+

Laptop Gigabyte MF F2VN333SH

+

Giá: 20.290.000đ

+
+ +
+
+
+
+ +
+

Laptop Gigabyte G5 KF-E3VN333SH

+

Giá: 23.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Gigabyte G5 GD-51VN123SO

+

Giá: 17.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Gigabyte G5 GE-51VN263SH

+

Giá: 17.890.000đ

+
+ +
+
+
+
+ +
+

Laptop Gigabyte G5 MD-51S1123SH

+

Giá: 17.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Giagabyte G5 ME-51VN263SH

+

Giá: 20.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Gigabyte U4 UD-70S1823SO

+

Giá: 23.490.000đ

+
+ +
+
+
+
+ +
+

Laptop Gigabyte G5 KE-52VN263SH

+

Giá: 21.390.000đ

+
+ +
+
+
+
+ +
+

Laptop GIGABYTE AORUS 5 SE4-73VN313SH

+

Giá: 18.890.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/hp.html b/Laptop/hp.html new file mode 100644 index 0000000..8a0a2ea --- /dev/null +++ b/Laptop/hp.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop hp

+
+
+
+ +
+

Laptop HP Gaming Victus 15-FA0115TX 7C0X1PA

+

Giá: 19.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop HP Envy X360 2IN1 14-ES0013

+

Giá: 17.990.000đ

+
+ +
+
+
+
+ +
+

Laptop HP Pavilion 14-DV2073TU 7C0P2PA

+

Giá: 17.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop HP Evy 13 BA1047 290F5UA

+

Giá: 15.990.000đ

+
+ +
+
+
+
+ +
+

Laptop HP Gaming Victus 15-FA0031DX 6503849

+

Giá: 16.790.000đ

+
+ +
+
+
+
+ +
+

Laptop HP Elitebook 630 G9 6M142PA

+

Giá: 17.490.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop HP Pavilion 15-EG2037TX 6K783PA

+

Giá: 14.990.000đ

+
+ +
+
+
+
+ +
+

Laptop HP 245 G9 6L1N8PA

+

Giá: 10.990.000đ

+
+ +
+
+
+
+ +
+

Laptop HP 240 G9 6L1Y2PA

+

Giá: 14.490.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/laptop-page3.html b/Laptop/laptop-page3.html new file mode 100644 index 0000000..2e4a461 --- /dev/null +++ b/Laptop/laptop-page3.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop msi

+ +
+
+
+ +
+

Laptop MSI Gaming Katana GF68 11UC-642VN i7-11800H

+

Giá: 19.890.000đ

+
+ +
+
+
+
+ +
+

Laptop MSI Prestige 12EVO A12M-089VN i7-1185G7

+

Giá: 26.890.000đ

+
+ +
+
+
+
+ +
+

Laptop MSI Modern 13 C12MO-660VN i5-1235U

+

Giá: 15.990.000đ

+
+ +
+
+ +
+
+
+ +
+

Laptop MSI Gaming Raider GE68HX 15VF-050VN i7-13900KS

+

Giá: 36.590.000đ

+
+ +
+
+
+
+ +
+

Laptop MSI Gaming Beta 13 B5EEK 036VN R7-6800H

+

Giá: 26.490.000đ

+
+ +
+
+
+
+ +
+

Laptop MSI Gaming Creator Z16 HX Studio B17VFTO-064VN i9-13900HF

+

Hàng sắp về

+
+ +
+
+
+ +
+
+
+ +
+

Laptop MSI Prestige 13 EVO-206VN i5-1037G5

+

Giá: 39.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop MSI Gaming GF63 14UCX-842VN i5-14900HS

+

Giá: 19.990.000đ

+
+ +
+
+
+
+ +
+

Laptop MSI Modern 14 B11MOU 852VN i5-1155G7

+

Giá: 11.490.000đ

+
+ +
+
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/lenovo.html b/Laptop/lenovo.html new file mode 100644 index 0000000..09d9d06 --- /dev/null +++ b/Laptop/lenovo.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop lenovo

+
+
+
+ +
+

Laptop Lenovo IdeaPad Gaming 3 15ACH6 82K2027QVN

+

Giá: 15.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo IdeaPad Slim 3 14IAH8 83EQ0005VN

+

Giá: 14.190.000đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo Ideapad Gaming 3 15ARH7 82SB00BBVN

+

Giá: 18.290.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Lenovo Yoga Slim 7 14ACN6 82N7002MVN

+

Giá: 20.490.000đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo Ideapad 3 15IAU7 82RK001GVN

+

Giá: 10.390.000đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo ThinkPad E14 21EB0063VN

+

Giá: 18.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Laptop Lenovo Thinkpad P14S G2 T 20VX008GVN

+

Giá: 31.190.000đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo Ideapad 3 14IAU7 82RJ001BVN

+

Giá: 12.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Lenovo IdeaPad 3 14ITL6 82H701QVVN

+

Giá: 15.490.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Laptop/microsoft.html b/Laptop/microsoft.html new file mode 100644 index 0000000..ccedbf8 --- /dev/null +++ b/Laptop/microsoft.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm laptop microsoft surface

+
+
+
+ +
+

Surface Pro 7 Plus

+

Giá: 17.990.000 đ

+
+ +
+
+
+
+ +
+

Laptop Surface Pro 9

+

Giá: 26.490.000đ

+
+ +
+
+
+
+ +
+

Surface Laptop Go Core i5 / 8GB / 128 GB / 12.4

+

Giá: 15.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Surface Pro 7

+

Giá: 19.990.000đ

+
+ +
+
+
+
+ +
+

Surface Pro 9

+

Giá: 23.990.000đ

+
+ +
+
+
+
+ +
+

Laptop Surface Pro 9 i7 16GB 256GB

+

Giá: 40.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Surface Pro 8 Core i5 / 8GB / 128GB

+

Giá: 22.990.000đ

+
+ +
+
+
+
+ +
+

Surface Laptop Go 12.4

+

Giá: 12.990.000đ

+
+ +
+
+
+
+ +
+

Surface Pro 9 i5 8GB 128GB

+

Giá: 23.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/MTB.html b/MTB.html new file mode 100644 index 0000000..20c3c07 --- /dev/null +++ b/MTB.html @@ -0,0 +1,431 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm máy tính bảng ipad

+
+
+
+ +
+

iPad Pro 11 inch 2022 M2 Wifi 128GB

+

Giá: 19.890.000 đ

+
+ +
+
+
+
+ +
+

iPad 10.2 2021 WiFi 64GB

+

Giá: 7.790.000đ

+
+ +
+
+
+
+ +
+

iPad Air 5 10.9 inch (2022) 64GB

+

Giá: 13.590.000đ

+
+ +
+
+ +
+
+
+
+ +
+

iPad Gen 10 10.9 inch 2022 64GB

+

Giá: 10.590.000đ

+
+ +
+
+
+
+ +
+

iPad mini 6 WiFi 64GB

+

Giá: 11.390.000đ

+
+ +
+
+
+
+ +
+

iPad Pro 11 2021 M1 128GB

+

Giá: 18.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

iPad Air 5 10.9 inch (2022) 256GB

+

Giá: 17.590.000đ

+
+ +
+
+
+
+ +
+

iPad Air 10.9 2020 64GB

+

Giá: 16.990.000đ

+
+ +
+
+
+
+ +
+

iPad Pro 11 inch 2022 M2 256GB

+

Giá: 23.190.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/PhuKien.html b/PhuKien.html new file mode 100644 index 0000000..b7af672 --- /dev/null +++ b/PhuKien.html @@ -0,0 +1,347 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+

sản phẩm hot

+ +
+ +
+

các sản phẩm tai nghe

+
+
+
+ +
+

Tai nghe choàng đầu có mic Gaming Soundmax AH335

+

Giá: 520.000đ

+
+ +
+
+
+
+ +
+

Tai nghe gaming Rapoo VH160 có mic

+

Giá: 390.000đ

+
+ +
+
+
+
+ +
+

Tai nghe gaming Rapoo VH520C có mic

+

Giá: 479.000đ

+
+ +
+
+
+
+
+
+ +
+

Tai nghe không dây Corsair HS70 PRO SE Cream/CA-9011210-AP

+

Giá: 2.850.000đ

+
+ +
+
+
+
+ +
+

Tai nghe HyperX Cloud II

+

Giá: 2.241.000đ

+
+ +
+
+
+
+ +
+

Tai nghe choàng đầu có mic Gaming Havit H2038U

+

Giá: 750.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/PhuKien1.html b/PhuKien1.html new file mode 100644 index 0000000..24f0609 --- /dev/null +++ b/PhuKien1.html @@ -0,0 +1,347 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+

sản phẩm hot

+ +
+ +
+

các sản phẩm bàn phím

+
+
+
+ +
+

Bàn phím cơ có dây iCore ICK10

+

Giá: 750.000đ

+
+ +
+
+
+
+ +
+

Bàn phím cơ không dây iCore G981

+

Giá: 1.920.000đ

+
+ +
+
+
+
+ +
+

Bộ bàn phím + Chuột Gaming iCore IGC01

+

Giá: 600.000đ

+
+ +
+
+
+
+
+
+ +
+

Bàn phím cơ không dây Zadez GT-015DK

+

Giá: 1.490.000đ

+
+ +
+
+
+
+ +
+

Bàn phím cơ có dây Corsair K60 Pro SE

+

Giá: 2.370.000đ

+
+ +
+
+
+
+ +
+

Bàn phím cơ có dây Corsair K60 PRO

+

Giá: 1.920.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/PhuKien2.html b/PhuKien2.html new file mode 100644 index 0000000..bfab431 --- /dev/null +++ b/PhuKien2.html @@ -0,0 +1,347 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+

sản phẩm hot

+ +
+ +
+

các sản phẩm chuột

+
+
+
+ +
+

Chuột Gaming Có Dây iCore GM03

+

Giá: 499.000đ

+
+ +
+
+
+
+ +
+

Chuột Gaming MSI Clutch GM20 Elite

+

Giá: 755.000đ

+
+ +
+
+
+
+ +
+

Chuột Gaming Zadez G156M

+

Giá: 289.000đ

+
+ +
+
+
+
+
+
+ +
+

Chuột Bluetooth Microsoft Modern

+

Giá: 810.000đ

+
+ +
+
+
+
+ +
+

Chuột Bluetooth Logitech M650

+

Giá: 765.000đ

+
+ +
+
+
+
+ +
+

Chuột có dây Prolink 1005

+

Giá: 107.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DT1plus.html b/Smartphone/DT1plus.html new file mode 100644 index 0000000..c4eb665 --- /dev/null +++ b/Smartphone/DT1plus.html @@ -0,0 +1,410 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại one plus

+
+
+
+ +
+

OnePlus 11 5G 8GB 128GB

+

Giá: 13.990.000đ

+
+ +
+
+
+
+ +
+

OnePlus Nord 3 5G 16GB 256GB

+

Giá: 10.990.000đ

+
+ +
+
+
+
+ +
+

OnePlus Nord CE 3 Lite

+

Giá: 5.690.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Oneplus Ace 2 Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

OnePlus 9 Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

OnePlus Nord N20 SE

+

Giá Liên Hệ

+
+ +
+
+ +
+
+
+
+ +
+

OnePlus Ace Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

OnePlus Nord CE

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

OnePlus Nord 2T

+

Giá Liên Hệ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DThuawei.html b/Smartphone/DThuawei.html new file mode 100644 index 0000000..0e1a92d --- /dev/null +++ b/Smartphone/DThuawei.html @@ -0,0 +1,410 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại huawei

+
+
+
+ +
+

Huawei P60 Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Huawei Nova 9 SE

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Huawei Nova 10 Pro

+

Giá Liên Hệ

+
+ +
+
+ +
+
+
+
+ +
+

Huawei P30 Lite

+

Giá: 7.490.000đ

+
+ +
+
+
+
+ +
+

Huawei P30

+

Giá: 17.990.000đ

+
+ +
+
+
+
+ +
+

Huawei P30 Pro

+

Giá: 23.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Huawei Nova 10z

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Huawei Nova 7 SE

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Huawei Nova Y60

+

Giá Liên Hệ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DToppo.html b/Smartphone/DToppo.html new file mode 100644 index 0000000..224d0be --- /dev/null +++ b/Smartphone/DToppo.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại oppo

+
+
+
+ +
+

OPPO Find N3 Flip 12GB 256GB

+

Giá: 22.990.000 đ

+
+ +
+
+
+
+ +
+

OPPO Find N3 16GB 512GB

+

Giá: 44.990.000đ

+
+ +
+
+
+
+ +
+

OPPO Reno10 5G 8GB 256GB

+

Giá: 10.490.000đ

+
+ +
+
+ +
+
+
+
+ +
+

OPPO Reno8 5G (8GB 256GB)

+

Giá: 7.990.000đ

+
+ +
+
+
+
+ +
+

OPPO A77s

+

Giá: 4.790.000đ

+
+ +
+
+
+
+ +
+

OPPO Reno8 T 4G 256GB

+

Giá: 6.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

OPPO Find N2 Flip

+

Giá: 17.790.000đ

+
+ +
+
+
+
+ +
+

OPPO Reno10 128GB

+

Giá: 9.690.000đ

+
+ +
+
+
+
+ +
+

OPPO A58 4G 6GB 128GB

+

Giá: 4.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DTpixel.html b/Smartphone/DTpixel.html new file mode 100644 index 0000000..70a6284 --- /dev/null +++ b/Smartphone/DTpixel.html @@ -0,0 +1,407 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại google pixel

+
+
+
+ +
+

Google Pixel 8 Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel 7 Pro

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel 6 Pro

+

Giá Liên Hệ

+
+ +
+
+ +
+
+
+
+ +
+

Google Pixel 7a

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel 5a

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel 4 XL

+

Giá Liên Hệ

+
+ +
+
+ +
+
+
+
+ +
+

Google Pixel 3 XL

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel 2 XL

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Google Pixel Fold

+

Giá Liên Hệ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DTrealme.html b/Smartphone/DTrealme.html new file mode 100644 index 0000000..8b0cde5 --- /dev/null +++ b/Smartphone/DTrealme.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại realme

+
+
+
+ +
+

Điện thoại realme C53 (6GB/128GB)

+

Giá: 3.890.000đ

+
+ +
+
+
+
+ +
+

Điện thoại realme C55 6GB

+

Giá: 4.390.000đ

+
+ +
+
+
+
+ +
+

Điện thoại realme 11 128GB

+

Giá: 6.490.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Điện thoại realme 10

+

Giá: 5.390.000đ

+
+ +
+
+
+
+ +
+

Điện thoại realme C51 (4GB/64GB)

+

Giá: 2.990.000đ

+
+ +
+
+
+
+ +
+

Realme 9 4G 8GB 128GB

+

Giá: 4.390.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Điện thoại realme C30s (3GB/64GB)

+

Giá: 2.690.000đ

+
+ +
+
+
+
+ +
+

Điện thoại realme 11 Pro+ 5G

+

Giá: 13.490.000đ

+
+ +
+
+
+
+ +
+

Điện thoại realme 11 Pro 5G

+

Giá: 10.690.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DTsamsung.html b/Smartphone/DTsamsung.html new file mode 100644 index 0000000..9a09557 --- /dev/null +++ b/Smartphone/DTsamsung.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại samsung

+
+
+
+ +
+

Samsung Galaxy S23 Ultra 256GB

+

Giá: 23.990.000 đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Z Flip5 512GB

+

Giá: 21.990.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy S22 Ultra (12GB - 256GB)

+

Giá: 17.750.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Samsung Galaxy S23 8GB 128GB

+

Giá: 15.490.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Z Fold5 12GB 256GB

+

Giá: 33.490.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Z Flip5 256GB

+

Giá: 19.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Samsung Galaxy M14 5G 4GB 128GB

+

Giá: 3.850.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy S22 Ultra (8GB - 128GB)

+

Giá: 16.650.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy S23 Ultra 12GB 512GB

+

Giá: 29.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DTvivo.html b/Smartphone/DTvivo.html new file mode 100644 index 0000000..da65faa --- /dev/null +++ b/Smartphone/DTvivo.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại vivo

+
+
+
+ +
+

Vivo V29E 8GB 256GB

+

Giá: 8.990.000 đ

+
+ +
+
+
+
+ +
+

Vivo V25 Pro 8GB 128GB

+

Giá: 7.990.000đ

+
+ +
+
+
+
+ +
+

Vivo Y36 8GB 128GB

+

Giá: 5.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Vivo Y17s 4GB 128GB

+

Giá: 3.990.000đ

+
+ +
+
+
+
+ +
+

Vivo V27e 8GB 256GB

+

Giá: 8.190.000đ

+
+ +
+
+
+
+ +
+

Vivo Y16 4GB 128GB

+

Giá: 3.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Vivo Y22S 8GB 128GB

+

Giá: 4.790.000đ

+
+ +
+
+
+
+ +
+

Vivo Y02t 4GB 64GB

+

Giá: 2.990.000đ

+
+ +
+
+
+
+ +
+

Vivo V25 5G 8GB 128GB

+

Giá: 4.990.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Smartphone/DTxiaomi.html b/Smartphone/DTxiaomi.html new file mode 100644 index 0000000..056ad06 --- /dev/null +++ b/Smartphone/DTxiaomi.html @@ -0,0 +1,416 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm điện thoại xiaomi

+
+
+
+ +
+

Xiaomi Redmi Note 12 8GB 128GB

+

Giá: 4.790.000 đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi 13C 6GB 128GB

+

Giá: 3.290.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Note 12 4GB 128GB

+

Giá: 3.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Xiaomi 13T Pro 5G (12GB - 512GB)

+

Giá: 15.490.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Note 12 Pro 5G

+

Giá: 8.490.000đ

+
+ +
+
+
+
+ +
+

Xiaomi 13T 12GB 256GB

+

Giá: 11.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Xiaomi Redmi 12C 4GB 64GB

+

Giá: 2.490.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Note 12 Pro 4G 8GB 256GB

+

Giá: 7.190.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Note 12S

+

Giá: 5.490.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Tablet/MTBhuawei.html b/Tablet/MTBhuawei.html new file mode 100644 index 0000000..16eb3d1 --- /dev/null +++ b/Tablet/MTBhuawei.html @@ -0,0 +1,301 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm máy tính bảng lenovo

+
+
+
+ +
+

Huawei MatePad C7

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

MatePad Pro 11

+

Giá Liên Hệ

+
+ +
+
+
+
+ +
+

Huawei Matepad

+

Giá Liên Hệ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Tablet/MTBlenovo.html b/Tablet/MTBlenovo.html new file mode 100644 index 0000000..9c3ffd2 --- /dev/null +++ b/Tablet/MTBlenovo.html @@ -0,0 +1,412 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm máy tính bảng lenovo

+
+
+
+ +
+

Lenovo Tab M10 Gen 3 4GB 64GB ZAAF0009VN

+

Giá: 4.890.000 đ

+
+ +
+
+
+
+ +
+

Lenovo Tab P11 Plus 4GB 64GB ZA9L0163VN

+

Giá: 5.490.000đ

+
+ +
+
+
+
+ +
+

Lenovo Yoga Tab 11

+

Giá: 8.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Lenovo Tab M8 Gen 2 3GB 32GB (ZA630033VN)

+

Giá: 1.990.000đ

+
+ +
+
+
+
+ +
+

Lenovo Tab M10 Gen 2 2GB 32GB

+

Giá: 3.490.000đ

+
+ +
+
+
+
+ +
+

Lenovo Legion Y900

+

Giá: 10.050.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Lenovo tab M10 Gen 3 (ZAAF0025VN)

+

Giá: 9.590.000đ

+
+ +
+
+
+
+ +
+

Lenovo Legion Y700

+

Giá: 19.090.000đ

+
+ +
+
+
+
+ +
+

Lenovo Tab M8

+

Giá: 5.690.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Tablet/MTBsamsung.html b/Tablet/MTBsamsung.html new file mode 100644 index 0000000..35daf65 --- /dev/null +++ b/Tablet/MTBsamsung.html @@ -0,0 +1,412 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm máy tính bảng samsung

+
+
+
+ +
+

Samsung Galaxy Tab S9 FE 5G 6GB 128GB

+

Giá: 10.890.000 đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S9 Ultra 12GB 256GB

+

Giá: 23.590.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab A9 WIFI 4GB 64GB

+

Giá: 3.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S9 Ultra 12GB 512GB

+

Giá: 25.590.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S9 Wifi 8GB 128GB

+

Giá: 17.090.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S8 5G

+

Giá: 16.990.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S9 FE WIFI 6GB 128GB

+

Giá: 9.590.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab S9 Wifi 12GB 256GB

+

Giá: 19.090.000đ

+
+ +
+
+
+
+ +
+

Samsung Galaxy Tab A9+ WIFI 4GB 64GB

+

Giá: 5.690.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Tablet/MTBxiaomi.html b/Tablet/MTBxiaomi.html new file mode 100644 index 0000000..8abbb46 --- /dev/null +++ b/Tablet/MTBxiaomi.html @@ -0,0 +1,412 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + +
+
+
+ +

sản phẩm hot

+ +
+ +
+

các sản phẩm máy tính bảng xiaomi

+
+
+
+ +
+

Xiaomi Pad 6 8GB 128GB

+

Giá: 8.490.000 đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Pad SE 6GB 128GB

+

Giá: 4.990.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Pad 6 8GB 256GB

+

Giá: 9.790.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Xiaomi Pad 5 (6GB/256GB)

+

Giá: 7.490.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Pad 6 Pro

+

Giá: 17.090.000đ

+
+ +
+
+
+
+ +
+

Redmi Pad 3GB 64GB

+

Giá: 5.050.000đ

+
+ +
+
+ +
+
+
+
+ +
+

Xiaomi Redmi Pad 2022

+

Giá: 9.590.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Pad 6 Max

+

Giá: 19.090.000đ

+
+ +
+
+
+
+ +
+

Xiaomi Redmi Pad SE 6GB 128GB

+

Giá: 5.690.000đ

+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: + Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản + phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, + P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, + Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, + Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/Web 1/LTWebvaUD_Nhom13_7/project b/Web 1/LTWebvaUD_Nhom13_7/project deleted file mode 160000 index a5ee2d1..0000000 --- a/Web 1/LTWebvaUD_Nhom13_7/project +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a5ee2d1f0de4daa2bb874ed84ad07fa039f11488 diff --git a/admin.html b/admin.html new file mode 100644 index 0000000..35b37ea --- /dev/null +++ b/admin.html @@ -0,0 +1,97 @@ + + + + + + + Administrator + + + + + + +
+ +
+ +
+ + + + +
+

Login Administrator

+
+
+ + + + +
+
+ + + + +
+
+ + Forgot Password? +
+ + +
+
+ +
+

Registration

+
+
+ + + + + +
+
+ + + + +
+
+ + + + +
+
+ +
+ + +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/admin1.html b/admin1.html new file mode 100644 index 0000000..4bbc847 --- /dev/null +++ b/admin1.html @@ -0,0 +1,220 @@ + + + +dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + +
+ + + +
+
+ +
+
+ +
+
+

Danh mục chức năng của admin:

+ +
+
+
+
+ +
+
+
+
+ + + + +
+
+
+ +
+
+
+ +
+ + + + + + +
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/calendar.html b/calendar.html new file mode 100644 index 0000000..af8769f --- /dev/null +++ b/calendar.html @@ -0,0 +1,211 @@ + + + +Calendar + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + +
+ + + +
+
+ +
+
+ +
+
+
+ +
+
+
+
+ + + + + +
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/checkout.html b/checkout.html new file mode 100644 index 0000000..3021447 --- /dev/null +++ b/checkout.html @@ -0,0 +1,280 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ lesongnhatquyen@gmail.com +

+

0993246149 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + +
+
+
+ Tiếp tục mua hàng +

Danh sách trong giỏ hàng

+
+
+ +
+
Sản phẩm 1
+
27.190.000đ/1 sản phẩm
+
+
2
+
54.380.000đ
+
+
+
+
+

Thanh toán

+
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+
+
+
Tổng số lượng
+
2
+
+
+
Tổng tiền
+
54.380.000đ
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ Video giới thiệu +
+
+ +
+
+
+
+ Bản đồ đường đi +
+
+ +
+
+
+
+
+
+
+ +
+
+
+

Chính sách bảo mật

+

Quy chế hoạt động

+

Hướng dẫn mua online

+

Hướng dẫn mua trả góp

+

Chính sách trả góp

+

Chính sách thu thập
và xử lý dữ liệu cá nhân

+

Chính sách đổi trả

+

Hệ thống bảo hành

+
+
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông và 105 Bà Huyện Thanh Quan, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + + + + + \ No newline at end of file diff --git a/css/Mystyles.css b/css/Mystyles.css index 0854671..d7e547a 100644 --- a/css/Mystyles.css +++ b/css/Mystyles.css @@ -70,10 +70,21 @@ } body,.jumbotron { - background-image: linear-gradient(to right bottom,#d4ccc3,#FFCC00); + /* background-image: linear-gradient(to right bottom,#d4ccc3,#FFCC00); */ + background-color: rgb(230, 223, 223); } img { - height: 50%; + width: 100% !important; + + object-fit: cover; + object-position: center; + padding-top: 10px; + padding-left: 5px; + padding-right: 5px; +} +.img2 { + width: 100% !important; + height: 100%; object-fit: cover; object-position: center; padding-top: 10px; @@ -88,6 +99,1230 @@ img { cursor: pointer; box-shadow: 0 0 5px 5px rgb(144, 112, 112); } -.card-link { +.card__link { + display: block !important; + width: 100%; + height: calc(100% - 55.67px); + text-decoration: none !important; +} +.image{ + width: 100%; + height: 70%; +} +.card-body { + height: 30% !important; + width: 100%; +} +.title-name { display: inline-block; + margin-right: 1rem; +} +.title { + margin-top: 1rem; + display: flex; + align-items: center; + justify-content: center; +} +.fa-star{ + color: red; +} +.carousel { + margin-top: 2rem; +} +.detail-title { + text-align: center; +} + table tr td { + border: 2px solid black !important; + +} +.table__column { + box-shadow: 0 0 5px 5px white; +} +.detail { + display: flex; + align-items: center; + justify-content: center; +} +.row-detail { + margin-top: 5rem !important; +} +.boxed-gb,.boxed-color{ + display: flex; + text-align: center; + justify-content: center; + margin-top: 1rem; +} +.boxed_data , .boxed-color-phone{ + display: block !important; + padding: 1rem; + border: 5px solid black; + color: red; + font-weight: 500; + cursor: pointer; +} +.boxed-gb .boxed_data:not(:nth-child(1)) { + margin-left: 1rem; +} +.boxed-color .boxed-color-phone:not(:nth-child(1)) { + margin-left: 1rem; +} +a{ + text-decoration: none !important; + color: blue; +} +.boxed_data:hover ,.boxed-color-phone:hover{ + background-image: linear-gradient(to right,blue ,red); + color: white; +} +.carousel { + display: flex; + align-items: center; + justify-content: center; +} +.carousel-caption { + color: rgb(150, 150, 232); +} +.iphone-click{ + + border-radius: 2rem; + padding: 1rem; + margin-top: 2rem; + display: flex; + text-align: center; + justify-content: center; + border: 5px solid black; +} +.contain-image-click { + width: 4rem; + height: 4rem; +} +ul li { + list-style-type: none; +} +.container-price{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 1rem; +} +.iphone { + width: 20rem; + margin-left: 1rem; +} +.list { + display: flex; + margin-left: -1rem; +} + +.line-middle{ + position: relative; + width: 200px; /* Đặt kích thước theo ý muốn */ + height: 200px; /* Đặt kích thước theo ý muốn */ +} +.line-middle::before{ + content:""; + width: 92.43px; + height: 2px; + background-color: black; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%,-50%); } +.price1 { + width: 25rem !important; + height: 3rem !important; + border-radius: 1rem; + color: black !important; + background-color: white; +}.price.active { + box-shadow: 0 0 3px 3px red; +} +.price { + border-radius: 50px; + margin-bottom: 2rem; +} +.price .active .line-middle0{ + color: red !important; +} +.cart-flex { + display: flex; + align-items: center; + justify-content: center; +} +.add-cart2{ + width: 18%; + height: 4rem !important ; + margin-left: 1rem; + border-radius: 3rem; + border: 2px solid black; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-top: 1rem; +} +.cart-flex { + display: flex; + align-items: center; + justify-content: center; +} +.buy2{ + margin-top: 1rem; + width: 49%; + border-radius: 5rem; +} +.cart-flex2 { + display: flex; + justify-content: space-between; + margin-bottom: 2rem; + margin-top: 1rem; +} +*{ + font-family: 'Times New Roman', Times, serif ; +} + +.image4 { + width: 3rem; + height: 3rem; +} +.content-detail{ + font-weight: 500; +} +input[type="checkbox"] { + display: none; +} +.content23 { + transition: all 0.25s linear; + display: none; +} +input[type="checkbox"]:checked ~ .content23 { + display: block; +} +.information-label{ + position: relative; +} +.information-label::after{ + font-size: 0.8rem; + content: "▲"; + position: absolute; + top: 50%; + left: 68%; + transform: translate(-50%,-50%); +} +.information { + margin-top: 1rem; +} +input[type="checkbox"]:checked + .information-label::after { + font-weight: 100; + font-size: 0.8rem; + content: "▼"; + position: absolute; + top: 50%; + left: 68%; + transform: translate(-50%,-50%); +} + +.title-name { + background-image: linear-gradient(to right bottom,rgb(117, 36, 117),rgb(100, 9, 9)); + color: transparent; + -webkit-background-clip: text; + background-clip: text; +} +.cart { + position: fixed; + top: 0; + right: -100%; + width: 360px; + min-height: 100vh; + padding: 20px; + background-color:white; + box-shadow: -2px 0 8px 10 px hsl(0 4% 15% / 10%); + transition: 0.3s; +} +.cart.active { + right: 0; + +} +.cart-title { + text-align: center; + font-size: 1.5rem !important; + font-weight: 600 !important; + margin-top: 2rem !important; +} +.cart-box { + display: grid !important; + grid-template-columns: 32% 50% 18% !important; + align-items: center !important; + gap: 1rem !important; + margin-top: 1rem !important; + +} +.cart-image{ + width: 100px !important; + height: 100px !important; + object-fit: contain !important; + padding: 10px !important; +} +.detail-box { + display: grid !important; + row-gap: 0.5rem !important; +} +.cart-product-title { + font-size: 1.1rem !important; + text-transform: uppercase !important; +} +.cart-price { + font-weight: 700 !important; +} +.cart-quantity { + border: 1px solid black !important; + outline-color: red !important; + width: 2.4rem; + text-align: center !important; +} +.cart-remove { + font-size: 24px !important; + color: red !important; + cursor: pointer; +} +.total { + display: flex !important; + justify-content: flex-end !important; + margin-top: 1.5rem !important; + border-top: 1px solid black !important; +} +.total-title { + font-size: 1rem; + font-weight: 600; +} +.total-price { + margin-left: 0.5rem; +} +.btn-buy{ + display: flex; + margin: 1.5rem auto 0 auto; + padding: 12px 20px; + border: none; + background-color: red; + color: white; + font-size: 1rem; + font-weight: 600; + cursor: pointer; +} + .section-title { + font-size: 1.5rem; + font-weight: 600; + text-align: center; + margin-bottom: 1.5rem; + } + #close-cart { + position: absolute; + top: 1rem; + right: 0.8rem; + font-size: 2rem; + color: black; + cursor: pointer; + z-index: 1000; + } + .nav-item.active { + background-color: #28a745; /* Background color when active */ + } + + .nav-item.active .nav-link { + color: #ffffff; /* Text color when active */ + } + #checkout-form { + display: none; + } + + .hidden { + display: none; + } + .cart-hover:hover{ + background-color: red; + color: white !important; + } + + /* trang checkout */ + .checkoutLayout { + display: grid; + grid-template-columns: repeat(2,1fr); + gap:50px; + padding: 20px; + } + .checkoutLayout .right{ + background-color: #5358b3; + border-radius: 20px; + padding: 40px; + color:#fff; + } + .checkout .list .item img { + height: 100px !important; + } + .checkout .right .form { + display: grid; + grid-template-columns: repeat(2,1fr); + gap:20px; + border-bottom: 1px solid #7a7fe2; + padding-bottom: 20px; + } + .checkoutLayout .form .group:nth-child(-n+3) { + grid-column-start: 1; + grid-column-end: 3; + } + .checkoutLayout .form input, .checkoutLayout .form select { + width: 100%; + padding: 10px 20px; + box-sizing: border-box; + border-radius: 20px; + margin-top: 10px; + border:none; + background-color: #6a6fc9; + color:#fff; + } + .checkoutLayout .row { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 10px; + } + .checkoutLayout .row div:nth-child(2) { + font-weight: bold; + font-size: x-large; + } + .buttonCheckout { + width: 100%; + height: 40px; + border: none; + border-radius: 20px; + margin-top: 20px; + font-weight: bold; + color:#fff; + background-color: #49d8b9; + } + .returnCart h1 { +border-top: 1px solid #eee; +padding: 20px 0; + } + .returnCart .list .item img { + height: 80 px; + } + .returnCart .item { + display: grid; + grid-template-columns: 80px 1fr 50px 80px; + align-items: center; + gap: 20px; + margin-bottom: 30px; + padding: 0 10px; + box-shadow:0 10px 20px #555; + border-radius: 20px; + } +.retunCart .item .name ,.returnCart .item .returnPrice { + font-style: x-large; + font-weight: bold; +} +.jumbotron { + margin-bottom: 0rem !important; +} + +.tieude { + text-align: center; + text-transform: uppercase; + font-size: 30px; + font-weight: 900; + margin-top: 15px; +} + +.navbar-nav .nav-link { + color: white !important; + /* Set the text color to white */ +} + +.card { + display: flex; + flex-direction: column; + height: 100%; + /* Thiết lập màu nền và viền ban đầu cho card */ + background-color: #ffffff; + /* Màu nền trắng */ + border: 1px solid #007BFF; + /* Màu viền tối */ + border-radius: 10px; + /* Bo tròn góc */ + transition: background-color 0.3s ease-in-out; + /* Hiệu ứng chuyển động cho màu nền */ + margin-bottom: 20px; + position: relative; + z-index: 1; +} + +/* Thay đổi màu nền và màu chữ của card khi di chuột qua */ +.card:hover { + background-color: orange; + /* Màu nền primary khi hover */ + color: #000; + /* Màu chữ trắng khi hover */ +} + +/* Thay đổi màu chữ của giá khi di chuột vào card */ +.card:hover .price { + color: yellow !important; + /* Màu chữ trắng khi hover */ +} + +.card-body { + display: flex; + flex-direction: column; +} + +.card-text { + margin-top: auto; +} + +.card-text sup { + vertical-align: super; + font-size: 70%; + margin-left: 2px; +} + +.card-text sup { + vertical-align: super; + font-size: 70%; + margin-left: 2px; +} + +.card-body { + flex-grow: 1; +} + +.card-footer { + flex-shrink: 0; +} + +.card img { + max-height: 100%; + width: 100%; + object-fit: cover; + /* Đảm bảo ảnh không bị méo khi điều chỉnh kích thước */ +} + +.custom-tab { + margin-top: 30px; + margin-left: 5px; + border: 2px solid #007BFF !important; + /* Màu primary */ + border-radius: 10px !important; + /* Bo tròn góc */ + color: #000 !important; + font-size: 20px; + background: transparent !important; + /* Nền trong suốt */ + padding: 10px 20px; + /* Khoảng cách nền và chữ */ +} + +.tab-pane { + background-color: none; + /* Màu nền xen kẽ */ + padding: 20px; +} + +/* CSS cho thanh tìm kiếm */ +.search-bar { + width: 300px !important; + /* Điều chỉnh chiều rộng tùy ý */ + padding: 10px; + /* Thêm padding để làm cho nó trông đẹp hơn */ +} + +/* Video - google Map */ +.video { + width: 100%; + float: left; + padding: 10px; + box-sizing: border-box; +} + +.googleMap { + width: 100%; + float: left; + box-sizing: border-box; + padding-top: 15px; + padding: 10px; +} + +.nav-item.nav-link { + font-size: 20px; +} + +.nav-link.active { + background-color: #4CAF50 !important; +} + +.nav-link:not(.active):hover { + color: yellow !important; + background-color: orange !important; +} + +.dropdown-item.active { + background-color: #4CAF50 !important; +} + +.dropdown-item:not(.active):hover { + color: yellow !important; + background-color: orange !important; +} + +p a { + color: white !important; + padding: 10px; +} + +p a:hover { + color: blue !important; +} + +.list-group-item.active { + background-color: #4CAF50 !important; + /* Mã màu xanh lá bạn muốn sử dụng */ + color: #fff; + /* Màu chữ sẽ hiển thị trên nền xanh lá */ + border: 1px solid #4CAF50 !important; + /* Thêm border style ở đây */ +} + +.list-group-item:not(.active):hover { + color: yellow !important; + background-color: orange !important; +} + +.list-group-item.my-font { + font-size: 1.75rem; +} + + +.card { + cursor: pointer; + box-shadow: 0 0 5px 5px rgb(144, 112, 112); +} + +body, +.container { + overflow-x: hidden; +} + +/* CSS Document */ +body, +html, +* { + margin: 0; + padding: 0; + border: none; + box-sizing: border-box; +} + +.container { + width: 1200px; + margin: 0 auto; +} + +/*Navigation*/ +#nav .topnav { + display: flex; + align-items: flex-start; + flex-wrap: wrap; + padding-top: 10px; + height: 60px; +} + +#nav .topnav .right { + list-style-type: none; + display: flex; + margin-left: auto; +} + +#nav .topnav .right button { + display: block; + background: none; + outline: none; + height: 25px; + text-align: center; + margin: 0 10px; + cursor: pointer; + color: #fff; + font-size: 12pt; +} + +#nav .topnav .right #btnlogout { + background-color: #fff; + color: #000; + list-style-type: none; + text-align: center; + height: 25px; + width: 100px; + line-height: 25px; + font-weight: bold; + border-radius: 8px; + display: none; + cursor: pointer; + margin: 0 auto; + animation: bottomup 0.5s; + z-index: 100; + +} + +#nav .topnav .right li:hover>#btnlogout { + display: block; +} + +#nav .topnav .right li>#btnlogout:hover { + background-color: #ff4700; + color: #fff; +} + +/*User*/ +.modal { + height: 100%; + width: 100%; + background-color: rgba(0, 0, 0, 0.6); + position: fixed; + top: 0; + left: 0; + display: none; + z-index: 10; + overflow-y: auto; +} + +#login { + width: 500px; + background-color: #fff; + margin: 100px auto 0 auto; + padding-bottom: 20px; + animation: topdown 0.7s; + position: relative; + z-index: 2000 !important; +} + +#login .close { + position: absolute; + right: 15px; + top: 0px; + font-size: 35pt; + transform: rotate(45deg); + background-color: transparent; + cursor: pointer; + outline: none; +} + +#login .close:hover { + color: #ff4700; +} + +#login h2 { + font-family: "Times New Roman"; + display: inline-block; + margin: 20px 0 10px 40px; + padding-bottom: 10px; + border-bottom: 5px solid #000; + font-weight: 900; +} + +#login .logininfo { + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} + +#login label { + display: block; + font-weight: bold; + font-size: 13pt; + margin-top: 5px; + cursor: pointer; +} + +#login input { + display: inline-block; + width: 250px; + border: 1px solid #ccc; + padding-left: 5px; + height: 40px; + line-height: 40px; + font-size: 13pt; + outline: none; +} + +#login input:focus { + border: 1px solid #ff4700; +} + +#login div[id*="error"] { + width: 100%; + background-color: #f2dede; + border: 1px solid #ebccd1; + color: #a94442; + font-weight: bold; + margin: 5px auto 0; + padding: 5px; + display: none; + cursor: default; +} + +#login #btnlogin { + display: block; + background-color: #ff4700; + width: 200px; + height: 40px; + border: 3px solid #ff4700; + margin: 50px auto 0; + font-size: 20pt; + line-height: 30px; + color: white; + border-radius: 999px; + cursor: pointer; + outline: none; + box-shadow: 2px 2px 10px 0 rgba(0, 0, 0, .7); +} + +#login p { + margin-top: 50px; + text-align: center; +} + +#login p a { + text-decoration: none; + color: #ff4700 !important; + font-weight: bold; +} + +#login #btnlogin:hover { + background-color: #fff; + color: #ff4700; +} + +#login #btnlogin:active { + box-shadow: none; +} + +#signup { + width: 700px; + background-color: #fff; + margin: 100px auto 0 auto; + padding-bottom: 20px; + animation: topdown 0.7s; + position: relative; + display: none; +} + +#signup .close { + position: absolute; + right: 15px; + top: 0px; + font-size: 35pt; + transform: rotate(45deg); + background-color: transparent; + cursor: pointer; + outline: none; +} + +#signup .close:hover { + color: #ff4700; +} + +#signup .signupinfo { + display: flex; + flex-wrap: wrap; + text-align: center; +} + +#signup .col { + width: 50%; + padding: 0 50px; +} + +#signup h2 { + font-family: "Times New Roman"; + display: inline-block; + margin: 20px 0 10px 40px; + padding-bottom: 10px; + border-bottom: 5px solid #000; + font-weight: 900; +} + +#signup label { + display: block; + font-weight: bold; + font-size: 13pt; + margin-top: 5px; + cursor: pointer; +} + +#signup input { + display: inline-block; + width: 250px; + border: 1px solid #ccc; + padding-left: 5px; + height: 40px; + line-height: 40px; + font-size: 13pt; + outline: none; +} + +#signup input:focus { + border: 1px solid #ff4700; +} + +#signup div[id*="error"] { + width: 100%; + background-color: #f2dede; + border: 1px solid #ebccd1; + color: #a94442; + font-weight: bold; + margin: 5px auto 0; + padding: 5px; + display: none; + cursor: default; +} + +#signup #btnsignup { + display: block; + background-color: #ff4700; + width: 200px; + height: 40px; + border: 3px solid #ff4700; + margin: 50px auto 0; + font-size: 20pt; + line-height: 30px; + color: white; + border-radius: 999px; + cursor: pointer; + outline: none; + box-shadow: 2px 2px 10px 0 rgba(0, 0, 0, .7); +} + +#signup p { + margin-top: 50px; + text-align: center; +} + +#signup p a { + text-decoration: none; + color: #ff4700 !important; + font-weight: bold; +} + +#signup #btnsignup:hover { + background-color: #fff; + color: #ff4700; +} + +#signup #btnsignup:active { + box-shadow: none; +} + +/*customalert*/ +#customalert { + visibility: hidden; + min-width: 250px; + color: #fff; + font-size: 14pt; + text-align: center; + border-radius: 2px; + padding: 20px; + position: fixed; + z-index: 100; + left: 50%; + top: 30px; + transform: translateX(-50%); +} + +#customalert.show { + visibility: visible; + animation: fadein 0.5s, fadeout 0.5s 3s; +} + +/*animation*/ +@keyframes fadein { + from { + top: 0; + opacity: 0; + } + + to { + top: 30px; + opacity: 1; + } +} + +@keyframes fadeout { + from { + top: 30px; + opacity: 1; + } + + to { + top: 0; + opacity: 0; + } +} + +@keyframes topdown { + 0% { + transform: translateY(-800px) + } + + 100% { + transform: translateY(0) + } +} + +@keyframes bottomup { + 0% { + transform: translateY(25px) + } + + 100% { + transform: translateY(0) + } +} + +@keyframes righttop { + 0% { + transform: scale(0); + transform-origin: 100% 0%; + } + + 100% { + transform: scale(1); + transform-origin: 100% 0%; + } +} + +@keyframes rightleft { + 0% { + right: -500px; + } + + 100% { + right: 0; + } +} + +@media screen and (max-width: 600px) { + .container { + width: 100%; + margin: 0 auto; + } + + /*Navigation*/ + #nav .topnav { + display: flex; + justify-content: center; + } + + #nav .topnav .right { + margin-left: 0; + } + + /*User*/ + #login { + width: 100%; + height: 100%; + margin: 0; + } + + #signup { + width: 100%; + height: 100%; + margin: 0; + overflow-y: auto; + } + + #signup .signupinfo { + flex-direction: column; + align-items: center; + } + + #signup .col { + width: auto; + padding: 0; + } +} + +@media screen and (min-width: 600px) and (max-width: 900px) { + .container { + width: 95%; + margin: 0 auto; + } + + /*Navigation*/ + #nav .topnav { + justify-content: center; + height: 40px; + } + + #nav .topnav .right { + margin-left: 0; + } + .btn123{ + width: 5rem; + height: 2rem; + } +.btn123:hover { + color: yellow !important; + background-color: orange !important; +} + /*User*/ + .modal { + height: 100%; + width: 100%; + background-color: rgba(0, 0, 0, 0.6); + position: fixed; + top: 0; + left: 0; + display: none; + z-index: 10; + } + + #signup { + width: 450px; + background-color: #fff; + margin: 30px auto 0; + } + + #signup .signupinfo { + flex-direction: column; + } + + #signup .col { + align-self: center; + width: auto; + padding: 0; + } +} + +@media screen and (min-width: 900px) and (max-width: 1200px) { + .container { + width: 90%; + } + + /*Navigation*/ + #nav .botnav { + display: flex; + height: 60px; + } + + #nav .botnav .logo img { + height: 60px; + } +} + +.trai { + float: left; + width: 30%; + padding: 5px; + text-align: center; +} + +.phai { + float: left; + width: 70%; + padding: 5px; +} + +.bigsize { + width: 70%; + height: auto; +} + +.khungImg { + width: 25%; + float: left; + padding: 5px; +} + +.khungImg img { + width: 100%; + height: auto; +} + +.tieude { + font-size: 40px; + font-weight: bold; + color: #007BFF; +} + +.gia { + font-size: 36px; + color: red; + font-weight: 900; +} + +.detail { + padding-left: 120px; + margin-bottom: 40px; +} + +.detail .info { + font-size: 30px; +} + +.detail p { + font-weight: bold; + color: #ff4700; +} + +.detail_bottom { + justify-content: center !important; + text-align: center !important; + align-items: center !important; +} + +.detail_bottom img { + padding-bottom: 30px; + margin-bottom: 30px; +} +.detail_bottom label{ + font-size: 24px; + font-weight: bold; +} +.detail_bottom .addtocart { + display: flex; + cursor: pointer; + font-size: 20pt; + padding: 10px 20px; + background-color: #ff4700; + color: #fff; + border: 2px solid #ff4700; + margin-left: 320px; +} + +.detail_bottom .addtocart:hover { + background-color: #fff; + color: #ff4700; + border: 2px solid #ff4700; +} + +.detail_bottom .quantitydown { + font-size: 14pt; + width: 40px; + height: 30px; +} + +.detail_bottom .quantityup { + font-size: 14pt; + width: 40px; + height: 30px +} + +.detail_bottom #quantity { + text-align: center; + font-size: 14pt; + width: 100px; + height: 30px; + padding: 5px; +} \ No newline at end of file diff --git a/detail.html b/detail.html new file mode 100644 index 0000000..3bf4725 --- /dev/null +++ b/detail.html @@ -0,0 +1,573 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ lesongnhatquyen@gmail.com +

+

0993246149 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + + +
+ +

Điện thoại IPhone 14 Pro Max

+ + + + + +
+
+
+ +
+

Chọn màu để xem giá và chi nhánh có hàng

+ +
+ 27.190.000đ +
29.990.000đ +
+
+
+ + + +
+
+ + +
+ +
+ + + +
    +
  • +
    + +
    +

    Máy mới 100% , chính hãng Apple Việt Nam. + HHPC hiện là đại lý bán lẻ uỷ quyền iPhone chính hãng VN/A của Apple Việt Nam

    +
  • +
  • +
    + +
    +

    Hộp, Sách hướng dẫn, Cây lấy sim, Cáp Lightning - Type C

    +
  • +
  • +
    + +
    +

    1 ĐỔI 1 trong 30 ngày nếu có lỗi phần cứng nhà sản xuất. Bảo hành 12 tháng tại trung tâm bảo hành chính hãng Apple: CareS

    +
  • +
  • +
    + +
    +

    Giá sản phẩm đã bao gồm VAT

    +
  • + +
+ +
+
+
+
+
+ + +
+
+
+ Chọn dung lượng cho máy +
+ 128GB + 256GB + 512GB + 1TB +
+ Chọn màu cho máy +
+ Đen + Tím + Vàng +
+

Cấu hình Điện thoại iPhone 14 Pro Max 256GB

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Màn hình: OLED6.7"Super Retina XDR
Hệ điều hành: IOS 16
Camera sau: Chính 48 MP & Phụ 12 MP, 12 MP
Camera trước: 12 MP
Chip: Apple A16 Bionic
RAM: 6 GB
Dung lượng lưu trữ: 256 GB
SIM: 1 Nano SIM & 1 eSIM, Hỗ trợ 5G
Pin, Sạc: 4323 mAh20 W
+
+ +
+
+
+

Những tính năng nổi bật

+

Màn hình Dynamic Island - Sự biến mất của màn hình tai thỏ thay thể bằng thiết kế viên thuốc, OLED 6,7 inch, hỗ trợ always-on display +
• Cấu hình iPhone 14 Pro Max mạnh mẽ, hiệu năng cực khủng từ chipset A16 Bionic +
• Làm chủ công nghệ nhiếp ảnh - Camera sau 48MP, cảm biến TOF sống động +
• Pin liền lithium-ion kết hợp cùng công nghệ sạc nhanh cải tiến +
• Thiết kế cao cấp bền bỉ +
• Nổi bật với thiết kế màn hình mới +
• Hiển thị nội dung chân thực hơn thông qua màn hình chất lượng +
• Bắt trọn mọi khoảnh khắc thông qua camera chính 48 MP +
• Hiệu năng đáng kinh ngạc với chip set Apple A16 Bionic +

+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ Video giới thiệu +
+
+ +
+
+
+
+ Bản đồ đường đi +
+
+ +
+
+
+
+
+
+
+ +
+
+
+

Chính sách bảo mật

+

Quy chế hoạt động

+

Hướng dẫn mua online

+

Hướng dẫn mua trả góp

+

Chính sách trả góp

+

Chính sách thu thập
và xử lý dữ liệu cá nhân

+

Chính sách đổi trả

+

Hệ thống bảo hành

+
+
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông và 105 Bà Huyện Thanh + Quan, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + + + \ No newline at end of file diff --git a/detail.js b/detail.js new file mode 100644 index 0000000..0d2d5c5 --- /dev/null +++ b/detail.js @@ -0,0 +1,148 @@ +document.addEventListener('DOMContentLoaded', function () { + var priceElements = document.querySelectorAll(".price"); + + priceElements.forEach(function (priceElement) { + priceElement.addEventListener('click', function () { + priceElement.classList.toggle('active'); + }); + }); + + var cartIcon = document.querySelector("#cart-icon"); + var cart = document.querySelector(".cart"); + var closeCart = document.querySelector("#close-cart"); + + cartIcon.onclick = () => { + cart.classList.add("active"); + }; + + closeCart.onclick = () => { + cart.classList.remove("active"); + }; + + if (document.readyState == "loading") { + document.addEventListener('DOMContentLoaded', ready); + } else { + ready(); + } + + function ready() { + var removeCartButtons = document.querySelectorAll(".cart-remove"); + for (var i = 0; i < removeCartButtons.length; i++) { + var button = removeCartButtons[i]; + button.addEventListener("click", removeCartItem); + } + + var quantityInputs = document.querySelectorAll(".cart-quantity"); + for (var i = 0; i < quantityInputs.length; i++) { + var input = quantityInputs[i]; + input.addEventListener("change", quantityChanged); + } + + var addCart = document.querySelectorAll(".add-cart"); + for (var i = 0; i < addCart.length; i++) { + var button = addCart[i]; + button.addEventListener("click", addCartClicked); + } + + document.querySelector(".btn-buy").addEventListener("click", buyButtonClicked); + } + + function buyButtonClicked() { + alert("Đơn hàng của bạn đã được đặt"); + var cartContent = document.querySelector(".cart-content"); + while (cartContent.hasChildNodes()) { + cartContent.removeChild(cartContent.firstChild); + } + updateTotal(); + } + + function quantityChanged(event) { + var input = event.target; + if (isNaN(input.value) || input.value <= 0) { + input.value = 1; + } + updateTotal(); + } + + function removeCartItem(event) { + var buttonClicked = event.target; + buttonClicked.parentElement.remove(); + updateTotal(); + } + + function addCartClicked(event) { + var button = event.target; + var shopProduct = button.closest(".card"); + var title = shopProduct.querySelector(".product-title").innerText; + var price = shopProduct.querySelector(".price").innerText; + var productImg = shopProduct.querySelector(".pro").src; + addProductToCart(title, price, productImg); + updateTotal(); + } + + function addProductToCart(title, price, productImg) { + var cartItems = document.querySelector(".cart-content"); + var cartItemsNames = cartItems.querySelectorAll(".cart-product-title"); + + for (var i = 0; i < cartItemsNames.length; i++) { + if (cartItemsNames[i].innerText === title) { + alert("Bạn đã thêm sản phẩm này vào giỏ hàng"); + return; + } + } + + var cartShopBox = document.createElement("div"); + cartShopBox.classList.add("cart-box"); + var cartBoxContent = ` + +
+
${title}
+
${formatMoney(price)}
+ +
+ + `; + cartShopBox.innerHTML = cartBoxContent; + cartItems.appendChild(cartShopBox); + + cartShopBox.querySelector(".cart-remove").addEventListener("click", removeCartItem); + cartShopBox.querySelector(".cart-quantity").addEventListener("change", quantityChanged); + } + + function updateTotal() { + var cartContent = document.querySelector(".cart-content"); + var cartBoxes = cartContent.getElementsByClassName("cart-box"); + var total = 0; + + for (var i = 0; i < cartBoxes.length; i++) { + var cartBox = cartBoxes[i]; + var priceElement = cartBox.querySelector(".cart-price"); + var quantityElement = cartBox.querySelector(".cart-quantity"); + + // Lấy textContent thay vì innerText để lấy toàn bộ nội dung văn bản + var priceText = priceElement.textContent.trim(); + + // Tách bỏ ký tự "đ" và thay thế dấu phẩy + var price = parseFloat(priceText.replace("đ", "").replace(/\./g, "").replace(",", ".")); + + var quantity = parseInt(quantityElement.value); + total += price * quantity; + } + + var totalFormatted = formatMoney(total); + document.querySelector(".total-price").innerText = totalFormatted; + } + + function formatMoney(number) { + // Sử dụng định dạng tiền tệ 'vi-VN' với đồng (VND) + return number.toLocaleString('vi-VN', { style: 'currency', currency: 'VND' }); + } +}); + +document.getElementById("btnBuy").addEventListener("click", function() { + // Thực hiện các thao tác cần thiết trước khi chuyển hướng + // Ví dụ: Lưu thông tin giỏ hàng vào localStorage + + // Chuyển hướng sang trang thanh toán + window.location.href = "checkout.html"; + }); \ No newline at end of file diff --git a/detail2.html b/detail2.html new file mode 100644 index 0000000..9d9db01 --- /dev/null +++ b/detail2.html @@ -0,0 +1,573 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ lesongnhatquyen@gmail.com +

+

0993246149 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + + +
+ +

Điện thoại IPhone 15 Pro Max

+ + + + + +
+
+
+ +
+

Chọn màu để xem giá và chi nhánh có hàng

+ +
+ 33.990.000đ +
35.990.000đ +
+
+
+ + + +
+
+ + +
+ +
+ + + +
    +
  • +
    + +
    +

    Máy mới 100% , chính hãng Apple Việt Nam. + HHPC hiện là đại lý bán lẻ uỷ quyền iPhone chính hãng VN/A của Apple Việt Nam

    +
  • +
  • +
    + +
    +

    Hộp, Sách hướng dẫn, Cây lấy sim, Cáp Lightning - Type C

    +
  • +
  • +
    + +
    +

    1 ĐỔI 1 trong 30 ngày nếu có lỗi phần cứng nhà sản xuất. Bảo hành 12 tháng tại trung tâm bảo hành chính hãng Apple: CareS

    +
  • +
  • +
    + +
    +

    Giá sản phẩm đã bao gồm VAT

    +
  • + +
+ +
+
+
+
+
+ + +
+
+
+ Chọn dung lượng cho máy +
+ 128GB + 256GB + 512GB + 1TB +
+ Chọn màu cho máy +
+ Đen + Tím + Vàng +
+

Cấu hình Điện thoại iPhone 14 Pro Max 256GB

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Màn hình: OLED6.7"Super Retina XDR
Hệ điều hành: IOS 16
Camera sau: Chính 48 MP & Phụ 12 MP, 12 MP
Camera trước: 12 MP
Chip: Apple A16 Bionic
RAM: 6 GB
Dung lượng lưu trữ: 256 GB
SIM: 1 Nano SIM & 1 eSIM, Hỗ trợ 5G
Pin, Sạc: 4323 mAh20 W
+
+ +
+
+
+

Những tính năng nổi bật

+

Màn hình Dynamic Island - Sự biến mất của màn hình tai thỏ thay thể bằng thiết kế viên thuốc, OLED 6,7 inch, hỗ trợ always-on display +
• Cấu hình iPhone 14 Pro Max mạnh mẽ, hiệu năng cực khủng từ chipset A16 Bionic +
• Làm chủ công nghệ nhiếp ảnh - Camera sau 48MP, cảm biến TOF sống động +
• Pin liền lithium-ion kết hợp cùng công nghệ sạc nhanh cải tiến +
• Thiết kế cao cấp bền bỉ +
• Nổi bật với thiết kế màn hình mới +
• Hiển thị nội dung chân thực hơn thông qua màn hình chất lượng +
• Bắt trọn mọi khoảnh khắc thông qua camera chính 48 MP +
• Hiệu năng đáng kinh ngạc với chip set Apple A16 Bionic +

+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ Video giới thiệu +
+
+ +
+
+
+
+ Bản đồ đường đi +
+
+ +
+
+
+
+
+
+
+ +
+
+
+

Chính sách bảo mật

+

Quy chế hoạt động

+

Hướng dẫn mua online

+

Hướng dẫn mua trả góp

+

Chính sách trả góp

+

Chính sách thu thập
và xử lý dữ liệu cá nhân

+

Chính sách đổi trả

+

Hệ thống bảo hành

+
+
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông và 105 Bà Huyện Thanh + Quan, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + + + \ No newline at end of file diff --git a/img/Laptop/brand/Gigabyte/gd51vn123so.jpg b/img/Laptop/brand/Gigabyte/gd51vn123so.jpg new file mode 100644 index 0000000..f88cc24 Binary files /dev/null and b/img/Laptop/brand/Gigabyte/gd51vn123so.jpg differ diff --git a/img/Laptop/brand/Gigabyte/ge51vn263sh.jpg b/img/Laptop/brand/Gigabyte/ge51vn263sh.jpg new file mode 100644 index 0000000..373ede5 Binary files /dev/null and b/img/Laptop/brand/Gigabyte/ge51vn263sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/ke52vn263sh.jpg b/img/Laptop/brand/Gigabyte/ke52vn263sh.jpg new file mode 100644 index 0000000..ffbb4ab Binary files /dev/null and b/img/Laptop/brand/Gigabyte/ke52vn263sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/kfe3vn333sh.jpg b/img/Laptop/brand/Gigabyte/kfe3vn333sh.jpg new file mode 100644 index 0000000..98cab28 Binary files /dev/null and b/img/Laptop/brand/Gigabyte/kfe3vn333sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/md51s1123sh.jpg b/img/Laptop/brand/Gigabyte/md51s1123sh.jpg new file mode 100644 index 0000000..3b199eb Binary files /dev/null and b/img/Laptop/brand/Gigabyte/md51s1123sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/me51vn263sh.jpg b/img/Laptop/brand/Gigabyte/me51vn263sh.jpg new file mode 100644 index 0000000..b535570 Binary files /dev/null and b/img/Laptop/brand/Gigabyte/me51vn263sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/mff2vn333sh.jpg b/img/Laptop/brand/Gigabyte/mff2vn333sh.jpg new file mode 100644 index 0000000..1edb68b Binary files /dev/null and b/img/Laptop/brand/Gigabyte/mff2vn333sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/se4_73vn313sh.jpg b/img/Laptop/brand/Gigabyte/se4_73vn313sh.jpg new file mode 100644 index 0000000..efe454d Binary files /dev/null and b/img/Laptop/brand/Gigabyte/se4_73vn313sh.jpg differ diff --git a/img/Laptop/brand/Gigabyte/text_ng_n_7__98.jpg b/img/Laptop/brand/Gigabyte/text_ng_n_7__98.jpg new file mode 100644 index 0000000..98cab28 Binary files /dev/null and b/img/Laptop/brand/Gigabyte/text_ng_n_7__98.jpg differ diff --git a/img/Laptop/brand/Gigabyte/ud70s1823so.jpg b/img/Laptop/brand/Gigabyte/ud70s1823so.jpg new file mode 100644 index 0000000..5008d7d Binary files /dev/null and b/img/Laptop/brand/Gigabyte/ud70s1823so.jpg differ diff --git a/img/Laptop/brand/MSI/637527995211621829_msi-prestige-14evo-xam-1-evoi5-dd.jpg b/img/Laptop/brand/MSI/637527995211621829_msi-prestige-14evo-xam-1-evoi5-dd.jpg new file mode 100644 index 0000000..4874202 Binary files /dev/null and b/img/Laptop/brand/MSI/637527995211621829_msi-prestige-14evo-xam-1-evoi5-dd.jpg differ diff --git a/img/Laptop/brand/MSI/637639340536799316_msi-gaming-gf63-den-5.jpg b/img/Laptop/brand/MSI/637639340536799316_msi-gaming-gf63-den-5.jpg new file mode 100644 index 0000000..b53a052 Binary files /dev/null and b/img/Laptop/brand/MSI/637639340536799316_msi-gaming-gf63-den-5.jpg differ diff --git a/img/Laptop/brand/MSI/637639340538048946_msi-gaming-gf63-den-3.jpg b/img/Laptop/brand/MSI/637639340538048946_msi-gaming-gf63-den-3.jpg new file mode 100644 index 0000000..822413d Binary files /dev/null and b/img/Laptop/brand/MSI/637639340538048946_msi-gaming-gf63-den-3.jpg differ diff --git a/img/Laptop/brand/MSI/637639340539455202_msi-gaming-gf63-den-4.jpg b/img/Laptop/brand/MSI/637639340539455202_msi-gaming-gf63-den-4.jpg new file mode 100644 index 0000000..0334ec6 Binary files /dev/null and b/img/Laptop/brand/MSI/637639340539455202_msi-gaming-gf63-den-4.jpg differ diff --git a/img/Laptop/brand/MSI/637639340540705429_msi-gaming-gf63-den-2.jpg b/img/Laptop/brand/MSI/637639340540705429_msi-gaming-gf63-den-2.jpg new file mode 100644 index 0000000..256d144 Binary files /dev/null and b/img/Laptop/brand/MSI/637639340540705429_msi-gaming-gf63-den-2.jpg differ diff --git a/img/Laptop/brand/MSI/637639340541330187_msi-gaming-gf63-den-1.jpg b/img/Laptop/brand/MSI/637639340541330187_msi-gaming-gf63-den-1.jpg new file mode 100644 index 0000000..f5a6d01 Binary files /dev/null and b/img/Laptop/brand/MSI/637639340541330187_msi-gaming-gf63-den-1.jpg differ diff --git a/img/Laptop/brand/MSI/637660079049990344_msi-gaming-gf66-rtx-3050-den-dd.jpg b/img/Laptop/brand/MSI/637660079049990344_msi-gaming-gf66-rtx-3050-den-dd.jpg new file mode 100644 index 0000000..f158653 Binary files /dev/null and b/img/Laptop/brand/MSI/637660079049990344_msi-gaming-gf66-rtx-3050-den-dd.jpg differ diff --git a/img/Laptop/brand/MSI/637663485438013374_msi-modern-14-xam-dd.jpg b/img/Laptop/brand/MSI/637663485438013374_msi-modern-14-xam-dd.jpg new file mode 100644 index 0000000..1800f17 Binary files /dev/null and b/img/Laptop/brand/MSI/637663485438013374_msi-modern-14-xam-dd.jpg differ diff --git a/img/Laptop/brand/MSI/638046281859179576_msi-gaming-katana-gf66-12u-den-dd-bh.jpg b/img/Laptop/brand/MSI/638046281859179576_msi-gaming-katana-gf66-12u-den-dd-bh.jpg new file mode 100644 index 0000000..91a1c9b Binary files /dev/null and b/img/Laptop/brand/MSI/638046281859179576_msi-gaming-katana-gf66-12u-den-dd-bh.jpg differ diff --git a/img/Laptop/brand/MSI/638224458137215624_msi-gaming-katana-gf66-12u-den-dd.jpg b/img/Laptop/brand/MSI/638224458137215624_msi-gaming-katana-gf66-12u-den-dd.jpg new file mode 100644 index 0000000..dac7c01 Binary files /dev/null and b/img/Laptop/brand/MSI/638224458137215624_msi-gaming-katana-gf66-12u-den-dd.jpg differ diff --git a/img/Smartphone/removebg-preview-1.png b/img/Smartphone/removebg-preview-1.png new file mode 100644 index 0000000..e300f51 Binary files /dev/null and b/img/Smartphone/removebg-preview-1.png differ diff --git a/img/Smartphone/removebg-preview-2.png b/img/Smartphone/removebg-preview-2.png new file mode 100644 index 0000000..43c0b86 Binary files /dev/null and b/img/Smartphone/removebg-preview-2.png differ diff --git a/img/Smartphone/removebg-preview-3.png b/img/Smartphone/removebg-preview-3.png new file mode 100644 index 0000000..c10ef58 Binary files /dev/null and b/img/Smartphone/removebg-preview-3.png differ diff --git a/img/Smartphone/removebg-preview-4.png b/img/Smartphone/removebg-preview-4.png new file mode 100644 index 0000000..7904839 Binary files /dev/null and b/img/Smartphone/removebg-preview-4.png differ diff --git a/img/Smartphone/removebg-preview-5.png b/img/Smartphone/removebg-preview-5.png new file mode 100644 index 0000000..6ab5bb4 Binary files /dev/null and b/img/Smartphone/removebg-preview-5.png differ diff --git a/index.html b/index.html index 126b979..891a68a 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@ + @@ -43,12 +44,12 @@

Shop Hoàn Hảo PC

Chào mừng quý khách đã đến với shop chúng tôi !


- lesongnhatquyen@gmail.com + lesongnhatquyen@gmail.com

-

0993246149 +

0993246149

- Đại học Sài Gòn + Đại học Sài Gòn

@@ -64,19 +65,19 @@

Shop Hoàn Hảo PC

@@ -222,70 +259,82 @@

các sản phẩm bán
- -
-

iPhone 14 Pro Max 256GB

-

Giá: 29.690.000đ

-
+ +
+ + +
+
+

iPhone 14 Pro Max 256GB

+

29.690.000đ

+
+
+ +
- -
-

Laptop Gigabyte Gaming MF-F2VN313SH

-

Giá: 21.290.000đ

-
+ +
+ + +
+
+

Laptop Gigabyte Gaming MF-F2VN313SH

+

21.290.000đ

+
+
+ +
- -
-

Samsung Galaxy S23 Ultra 5G 256GB

-

Giá: 22.990.000đ

-
+ +
+ + +
+
+

Samsung Galaxy S23 Ultra 5G 256GB

+

22.990.000đ

+
+
+ +
- -
-

Samsung Galaxy Tab S6 Lite

-

Giá: 6.990.000đ

-
+ +
+ + +
+
+

Samsung Galaxy Tab S6 Lite

+

6.990.000đ

+
+
+ +
@@ -294,70 +343,83 @@

các sản phẩm đư
- -
-

iPhone 15 Pro Max 256GB

-

Giá: 33.990.000đ

-
+ +
+ + +
+
+

iPhone 15 Pro Max 256GB

+

33.990.000đ

+
+
+ +
- -
-

Samsung Galaxy S24 Ultra 5G 256GB

-

Giá: 31.990.000đ

-
+ +
+ + +
+
+

Samsung Galaxy S24 Ultra 5G 256GB

+

31.990.000đ

+
+
+ +
- -
-

Samsung Galaxy Z Flip5 5G 256GB

-

Giá: 16.990.000đ

-
+ +
+ + +
+
+

Samsung Galaxy Z Flip5 5G 256GB

+

16.990.000đ

+
+
+ +
+
- -
-

Samsung Galaxy Z Fold5 5G 256GB

-

Giá: 29.990.000đ

-
+ +
+ + +
+
+

Samsung Galaxy Z Fold5 5G 256GB

+

Giá: 29.990.000đ

+
+
+ +
@@ -396,7 +458,7 @@

Samsung Galaxy Z Fold5 5G 256GB

@@ -433,38 +495,36 @@

Samsung Galaxy Z Fold5 5G 256GB

Giới thiệu về công ty

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và - các loại Phụ kiện khác đi kèm.

+ các loại Phụ kiện khác đi kèm.

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính - hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín - của doanh nghiệp.

+ hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

Kết nối với chúng tôi
- - - - - - - -
-
+ + + + + + +
+
Hệ thống cửa hàng
-

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

-

CS1: 28 Nguyễn Thông và 105 Bà Huyện Thanh - Quan, Q.3, TP.HCM

-

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

-
-
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông và 105 Bà Huyện Thanh Quan, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
Hỗ trợ thanh toán:
- - - -
+ + + +
@@ -472,8 +532,68 @@
Hỗ trợ thanh toán:

© Nhóm A07 2023-2024

- + + +
+ + + + + \ No newline at end of file diff --git a/index2.html b/index2.html new file mode 100644 index 0000000..9a4a299 --- /dev/null +++ b/index2.html @@ -0,0 +1,492 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + + +
+
+
+

Đồng hồ thông minh

+
+
+
+ +
+

Đồng hồ thông minh Samsung Galaxy Watch6 40mm

+

Giá: 6.990.000đ

+
+ +
+
+
+
+ +
+

Google Pixel Watch 2022

+

Giá: 4.490.000đ

+
+ +
+
+
+
+ +
+

Đồng hồ thông minh Apple Watch Ultra 2 GPS + Cellular 49mm viền Titanium dây Alpine size M

+

Giá: 21.990.000đ

+
+ +
+
+
+
+ +
+

Đồng hồ thông minh Apple Watch Ultra GPS + Cellular 49mm viền Titanium dây Alpine size M

+

Giá: 19.990.000đ

+
+ +
+
+ +
+

Tai nghe

+
+
+
+ +
+

Tai nghe Bluetooth AirPods Pro Gen 2 MagSafe Charge (USB-C) Apple MTJV3

+

Giá: 5.990.000đ

+
+ +
+
+
+
+

 

+ +
+

Tai nghe Bluetooth AirPods 3 Lightning Charge Apple MPNY3

+

Giá: 4.290.000đ

+
+ +
+
+
+
+ +
+

Tai nghe Bluetooth AirPods Pro (2nd Gen) MagSafe Charge Apple MQD83

+

Giá: 5.890.000đ

+
+ +
+
+
+
+ +
+

Tai nghe Bluetooth AirPods 2 Lightning Charge Apple MV7N2

+

Giá: 2.750.000đ

+
+ +
+
+ +
+

Macbook air

+
+
+
+ +
+

MacBook Pro 16 inch M3 Max 2023 14-core CPU

+

Giá: 89.990.000đ

+
+ +
+
+
+
+ +
+

SamSung Galaxy A54 5G

+

Giá: 31.490.000đ

+
+ +
+
+
+
+ +
+

MacBook Pro 13 inch M2 2022 10-core GPU

+

Giá: 39.890.000đ

+
+ +
+
+
+
+ +
+

MacBook Air 13 inch M1 2020 7-core GPU

+

Giá: 29.990.000đ

+
+ +
+
+ +
+
+
+
+ + + +
+
+
+
+
+
+ Video giới thiệu +
+
+ +
+
+
+
+ Bản đồ đường đi +
+
+ +
+
+
+
+
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/index3.html b/index3.html new file mode 100644 index 0000000..35369fc --- /dev/null +++ b/index3.html @@ -0,0 +1,488 @@ + + + + + HHPC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ HHPC logo +
+
+

Shop Hoàn Hảo PC

+

Chào mừng quý khách đã đến với shop chúng tôi !

+
+

+ dhsg@sgu.edu.vn +

+

028.38352309 +

+

+ Đại học Sài Gòn +

+
+
+
+
+ + + + + +
+
+
+

Tablet

+
+
+
+ +
+

iPad Air 5 M1 WiFi 64GB

+

Giá: 14.090.000đ

+
+ +
+
+
+
+ +
+

iPad 10 WiFi

+

Giá: 10.990.000đ

+
+ +
+
+
+
+ +
+

iPad Pro M2 11 inch WiFi

+

Giá: 17.990.000đ

+
+ +
+
+
+
+ +
+

iPad Gen 9 2021 10.2 inch 64GB

+

Giá: 7.790.000đ

+
+ +
+
+ +
+

Phần mềm văn phòng

+
+
+
+ +
+

Microsoft Office Home & Student 2021 chính hãng

+

Giá: 2.190.000đ

+
+ +
+
+
+
+ +
+

Kaspersky Plus 01 PC chính hãng

+

Giá: 290.000đ

+
+ +
+
+
+
+ +
+

ESET NOD32 Antivirus chính hãng

+

Giá: 150.000đ

+
+ +
+
+
+
+ +
+

ESET Internet Security chính hãng

+

Giá: 290.000đ

+
+ +
+
+ +
+
+ +
+

Microsoft 365 Personal 32/64bit chính hãng

+

Giá: 990.000đ

+
+ +
+
+
+
+ +
+

Microsoft 365 Family 32/64bit chính hãng

+

Giá: 1.490.000đ

+
+ +
+
+
+
+ +
+

Microsoft Windows 11 Home 64-bit chính hãng

+

Giá: 3.490.000đ

+
+ +
+
+
+
+ +
+

Microsoft Windows 11 Pro 64-bit chính hãng

+

Giá: 5.490.000đ

+
+ +
+
+ +
+
+
+
+ + + +
+
+
+
+
+
+ Video giới thiệu +
+
+ +
+
+
+
+ Bản đồ đường đi +
+
+ +
+
+
+
+
+
+
+ +
+
+ +
+
Giới thiệu về công ty
+

Hoản Hảo PC là 1 hệ thống cửa hàng lớn chuyên về các thiết bị điện tử thông minh như: Laptop, Điện thoại và + các loại Phụ kiện khác đi kèm.

+

HHPC shop sẽ cung cấp tới mọi tầng lớp khách hàng trải nghiệm mua sắm tích cực, từ sản phẩm Kỹ thuật số chính + hãng chất lượng cao, giá cả cạnh tranh đi kèm dịch vụ chăm sóc khách hàng thân thiện, được đảm bảo bởi uy tín + của doanh nghiệp.

+
Kết nối với chúng tôi
+ + + + + + + +
+
+
Hệ thống cửa hàng
+

CSC: 273 An Dương Vương, P.3, Q.5, TP.HCM

+

CS1: 28 Nguyễn Thông, Q.3, TP.HCM

+

CS2: 04 Tôn Đức Thắng, Q.1, TP.HCM

+
+
+
Hỗ trợ thanh toán:
+ + + +
+
+
+
+
+

© Nhóm A07 2023-2024

+
+ + + + \ No newline at end of file diff --git a/js/MyJS.js b/js/MyJS.js new file mode 100644 index 0000000..a1ca406 --- /dev/null +++ b/js/MyJS.js @@ -0,0 +1,265 @@ +function getLocation() { + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition(showPosition, showError, { enableHighAccuracy: true }); + } else { + console.error("Trình duyệt không hỗ trợ định vị địa lý."); + } +} + +function showPosition(position) { + var latitude = position.coords.latitude; + var longitude = position.coords.longitude; + + // Đoạn mã ở đây để sử dụng latitude và longitude mà không hiển thị thông báo + console.log("Vị trí của bạn là: " + latitude + ", " + longitude); +} + +function showError(error) { + switch (error.code) { + case error.PERMISSION_DENIED: + console.error("Người dùng từ chối yêu cầu định vị địa lý."); + break; + case error.POSITION_UNAVAILABLE: + console.error("Thông tin vị trí không khả dụng."); + break; + case error.TIMEOUT: + console.error("Yêu cầu lấy vị trí đã quá thời gian."); + break; + case error.UNKNOWN_ERROR: + console.error("Đã xảy ra lỗi không xác định."); + break; + } +} + +// JavaScript Document +/*USER*/ +function showform() { + var userform = document.getElementById('user'); + userform.style.display = 'block'; +} + +function closeform() { + var userform = document.getElementById('user'); + userform.style.display = 'none'; +} + +function showSignUp() { + document.getElementById('login').style.display = 'none'; + document.getElementById('signup').style.display = 'block'; +} + +function showLogin() { + document.getElementById('signup').style.display = 'none'; + document.getElementById('login').style.display = 'block'; +} + +document.getElementById('signupform').addEventListener('submit', createUser); +document.getElementById('loginform').addEventListener('submit', login); + +function createUser(e) { + e.preventDefault(); + var fullname = document.getElementById('fullname'); + var address = document.getElementById('address'); + var phone = document.getElementById('phone'); + var username = document.getElementById('usernameSignUp'); + var password = document.getElementById('passwordSignUp'); + var password2 = document.getElementById('passwordSignUp2'); + var flag = true; + if (!fullname.value) { + document.getElementById('fullnameerror').style.display = 'block'; + flag = false; + } else { + document.getElementById('fullnameerror').style.display = 'none'; + } + if (!address.value) { + document.getElementById('addresserror').style.display = 'block'; + flag = false; + } else { + document.getElementById('addresserror').style.display = 'none'; + } + if (!phone.value) { + document.getElementById('phoneerror').style.display = 'block'; + flag = false; + } else { + if (isNaN(Number(phone.value))) { + document.getElementById('phoneerror').style.display = 'block'; + document.getElementById('phoneerror').innerHTML = 'Số điện thoại không hợp lệ'; + flag = false; + } else { + if (Number(phone.value) < 100000000 || Number(phone.value) > 999999999) { + document.getElementById('phoneerror').style.display = 'block'; + document.getElementById('phoneerror').innerHTML = 'Số điện thoại không đúng'; + flag = false; + } else { + document.getElementById('phoneerror').style.display = 'none'; + } + } + } + if (!username.value) { + document.getElementById('usererror').style.display = 'block'; + flag = false; + } else { + document.getElementById('usererror').style.display = 'none'; + } + if (!password.value) { + document.getElementById('passworderror').style.display = 'block'; + flag = false; + } else { + if (password.value.length < 8) { + document.getElementById('passworderror').style.display = 'block'; + document.getElementById('passworderror').innerHTML = 'Mật khẩu phải trên 8 ký tự'; + flag = false; + } else { + document.getElementById('passworderror').style.display = 'none'; + } + } + if (password2.value != password.value) { + document.getElementById('password2error').style.display = 'block'; + flag = false; + } else { + document.getElementById('password2error').style.display = 'none'; + } + if (flag == false) { + return false; + } + var d = new Date(); + var datesignup = d.getDate() + '-' + (d.getMonth() + 1) + '-' + d.getFullYear(); + var user = { + username: username.value, + password: password.value, + fullname: fullname.value, + address: address.value, + phone: phone.value, + datesignup: datesignup + }; + var userArray = JSON.parse(localStorage.getItem('user')); + for (var i = 0; i < userArray.length; i++) { + if (user.username == userArray[i].username) { + document.getElementById('usererror').style.display = 'block'; + document.getElementById('usererror').innerHTML = 'Tên đăng nhập đã có người sử dụng'; + username.focus(); + return false; + } + } + userArray.push(user); + localStorage.setItem('user', JSON.stringify(userArray)); + customAlert('Bạn đã đăng ký thành công!', 'success'); + showLogin(); +} + +function login(e) { + e.preventDefault(); + var username = document.getElementById('usernameLogin').value; + var password = document.getElementById('passwordLogin').value; + var flag = true; + if (!username) { + document.getElementById('usernameerror').style.display = 'block'; + flag = false; + } else { + document.getElementById('usernameerror').style.display = 'none'; + } + if (!password) { + document.getElementById('passwordloginerror').style.display = 'block'; + flag = false; + } else { + document.getElementById('passwordloginerror').style.display = 'none'; + } + if (flag == false) { + return false; + } + var userArray = JSON.parse(localStorage.getItem('user')); + for (var i = 0; i < userArray.length; i++) { + if (username == userArray[i].username) { + if (password == userArray[i].password) { + closeform(); + localStorage.setItem('userlogin', JSON.stringify(userArray[i])); + window.location.reload(true); + return true; + } + } + } + document.getElementById('passwordloginerror').style.display = 'block'; + document.getElementById('passwordloginerror').innerHTML = 'Sai thông tin đăng nhập'; + return false; +} + +function logout(url) { + localStorage.removeItem('userlogin'); + localStorage.removeItem('cart'); + location.href = url; +} + +function checklogin() { + if (localStorage.getItem('userlogin')) { + var user = JSON.parse(localStorage.getItem('userlogin')); + var s = ''; + if (user.username == 'admin') { + s = '
  • ' + + '
  • ' + + '
  • ' + + '
  • '; + } else { + s = '
  • ' + + '
  • ' + + '
  • '; + } + document.querySelector('#nav .topnav ul.right').innerHTML = s; + } +} + +function checklogin2() { + if (localStorage.getItem('userlogin')) { + var user = JSON.parse(localStorage.getItem('userlogin')); + var s = ''; + if (user.username == 'admin') { + s = '
  • ' + + '
  • ' + + '
  • ' + + '
  • '; + } else { + s = '
  • ' + + '
  • ' + + '
  • '; + } + document.querySelector('#nav .topnav ul.right').innerHTML = s; + } +} + +/*END USER*/ + +/*CUSTOM ALERT BOX*/ +function customAlert(message, type) { + if (type == 'success') { + document.getElementById("customalert").style.backgroundColor = '#4CAF50'; + } + if (type == 'warning') { + document.getElementById("customalert").style.backgroundColor = '#f44336'; + } + document.getElementById("customalert").innerHTML = message; + var x = document.getElementById("customalert"); + x.className = "show"; + setTimeout(function () { + x.className = x.classList.remove("show"); + }, 3500); +} +function searchProducts() { + var searchTerm = document.getElementById('searchInput').value.toLowerCase(); + var products = document.querySelectorAll('.card'); + + products.forEach(function (product) { + var title = product.querySelector('.product-title').textContent.toLowerCase(); + if (title.includes(searchTerm)) { + product.style.display = 'block'; + } else { + product.style.display = 'none'; + } + }); + + // Hiển thị lại tất cả sản phẩm nếu ô tìm kiếm trống + if (searchTerm === '') { + products.forEach(function (product) { + product.style.display = 'block'; + }); + } +} + diff --git a/js/bootstrap.min.js b/js/bootstrap.min.js new file mode 100644 index 0000000..c8f82e5 --- /dev/null +++ b/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/js/category.js b/js/category.js new file mode 100644 index 0000000..bf50ae6 --- /dev/null +++ b/js/category.js @@ -0,0 +1,33 @@ +checkSearching(); +// Hàm checkSearching +function checkSearching() { + fetch(productApi) + .then((response) => response.json()) + .then((products) => { + let searchingData = localStorage.getItem('searching'); + + if (searchingData){ + var container = document.getElementById('body'); + var htmls = ' '; + var filteredProducts = products.filter((element) => + element.name.toLowerCase().indexOf(searchingData.toLocaleLowerCase()) >= 0 + ); + + filteredProducts.forEach((element) => { + if (element.status === 'Enabled'){ + htmls += + `
    + +

    ${element.name}

    + ★★★★★ +

    ${element.price}

    +
    + `; + } + }); + container.innerHTML = htmls; + localStorage.removeItem("searching"); + } + }); +} diff --git a/js/checkout.js b/js/checkout.js new file mode 100644 index 0000000..cdc36f9 --- /dev/null +++ b/js/checkout.js @@ -0,0 +1,61 @@ + +let listCart = []; + +function checkCart() { + var cookieValue = document.cookie + .split('; ') + .find(row => row.startsWith("listCart=")); + + if (cookieValue) { + listCart = JSON.parse(cookieValue.split("=")[1]); + } +} + +function addCartToHTML() { + let listCartHTML = document.querySelector(".returnCart .list"); + listCartHTML.innerHTML = ''; + + let totalQuantityHTML = document.querySelector(".totalQuantity"); + let totalPriceHTML = document.querySelector(".totalPrice"); + + let totalQuantity = 0; + let totalPrice = 0; + + if (listCart) { + listCart.forEach(product => { + if (product) { + let newP = document.createElement("div"); + newP.classList.add("item"); + + newP.innerHTML = ` +
    +
    ${product.name}
    +
    ${formatMoney(product.price)}đ/1 sản phẩm
    +
    +
    ${product.quantity}
    +
    ${formatMoney(product.price * product.quantity)}đ
    `; + + listCartHTML.appendChild(newP); + totalQuantity = totalQuantity + product.quantity; + totalPrice = totalPrice + product.price * product.quantity; + } + }); + } + + totalQuantityHTML.innerText = totalQuantity; + totalPriceHTML.innerText = formatMoney(totalPrice); +} + +function formatMoney(number) { + // Sử dụng định dạng tiền tệ 'vi-VN' với đồng (VND) + return number.toLocaleString('vi-VN', { style: 'currency', currency: 'VND' }); +} + +document.getElementById("btnBuy").addEventListener("click", function () { + // Cập nhật thông tin giỏ hàng + checkCart(); + addCartToHTML(); + + // Chuyển hướng đến trang checkout.html và truyền thông tin giỏ hàng qua URL + window.location.href = "checkout.html?cart=" + encodeURIComponent(JSON.stringify(listCart)); +}); diff --git a/js/generalFunction.js b/js/generalFunction.js new file mode 100644 index 0000000..df1fab8 --- /dev/null +++ b/js/generalFunction.js @@ -0,0 +1,9 @@ +const searchInput = document.getElementById('search-inp'); +const searchButton = document.getElementById('button-addon2'); + +// Xử lý sự kiện khi nhấn nút tìm kiếm +searchButton.addEventListener('click', function(){ + localStorage.setItem('searching', searchInput.value); + window.location.href = 'index.html'; + //gọi hàm checkSearching để hiển thị sản phẩm tìm kiếm +}); diff --git a/js/jquery-2.1.4.min.js b/js/jquery-2.1.4.min.js new file mode 100644 index 0000000..49990d6 --- /dev/null +++ b/js/jquery-2.1.4.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ +return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
    '; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ''; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += ''; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '
    '; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.delegate(selector, 'mouseout', function() { + $(this).removeClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); + }) + .delegate(selector, 'mouseover', function(){ + if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { + $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + $(this).addClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); + } + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find(document.body).append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.9.2"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); + +(function( $, undefined ) { + +var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ", + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }; + +$.widget("ui.dialog", { + version: "1.9.2", + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: "close", + dialogClass: "", + draggable: true, + hide: null, + height: "auto", + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: "center", + at: "center", + of: window, + collision: "fit", + // ensure that the titlebar is never outside the document + using: function( pos ) { + var topOffset = $( this ).css( pos ).offset().top; + if ( topOffset < 0 ) { + $( this ).css( "top", pos.top - topOffset ); + } + } + }, + resizable: true, + show: null, + stack: true, + title: "", + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr( "title" ); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + this.oldPosition = { + parent: this.element.parent(), + index: this.element.parent().children().index( this.element ) + }; + this.options.title = this.options.title || this.originalTitle; + var that = this, + options = this.options, + + title = options.title || " ", + uiDialog, + uiDialogTitlebar, + uiDialogTitlebarClose, + uiDialogTitle, + uiDialogButtonPane; + + uiDialog = ( this.uiDialog = $( "
    " ) ) + .addClass( uiDialogClasses + options.dialogClass ) + .css({ + display: "none", + outline: 0, // TODO: move to stylesheet + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + .attr( "tabIndex", -1) + .keydown(function( event ) { + if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + that.close( event ); + event.preventDefault(); + } + }) + .mousedown(function( event ) { + that.moveToTop( false, event ); + }) + .appendTo( "body" ); + + this.element + .show() + .removeAttr( "title" ) + .addClass( "ui-dialog-content ui-widget-content" ) + .appendTo( uiDialog ); + + uiDialogTitlebar = ( this.uiDialogTitlebar = $( "
    " ) ) + .addClass( "ui-dialog-titlebar ui-widget-header " + + "ui-corner-all ui-helper-clearfix" ) + .bind( "mousedown", function() { + // Dialog isn't getting focus when dragging (#8063) + uiDialog.focus(); + }) + .prependTo( uiDialog ); + + uiDialogTitlebarClose = $( "" ) + .addClass( "ui-dialog-titlebar-close ui-corner-all" ) + .attr( "role", "button" ) + .click(function( event ) { + event.preventDefault(); + that.close( event ); + }) + .appendTo( uiDialogTitlebar ); + + ( this.uiDialogTitlebarCloseText = $( "" ) ) + .addClass( "ui-icon ui-icon-closethick" ) + .text( options.closeText ) + .appendTo( uiDialogTitlebarClose ); + + uiDialogTitle = $( "" ) + .uniqueId() + .addClass( "ui-dialog-title" ) + .html( title ) + .prependTo( uiDialogTitlebar ); + + uiDialogButtonPane = ( this.uiDialogButtonPane = $( "
    " ) ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); + + ( this.uiButtonSet = $( "
    " ) ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + uiDialog.attr({ + role: "dialog", + "aria-labelledby": uiDialogTitle.attr( "id" ) + }); + + uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); + this._hoverable( uiDialogTitlebarClose ); + this._focusable( uiDialogTitlebarClose ); + + if ( options.draggable && $.fn.draggable ) { + this._makeDraggable(); + } + if ( options.resizable && $.fn.resizable ) { + this._makeResizable(); + } + + this._createButtons( options.buttons ); + this._isOpen = false; + + if ( $.fn.bgiframe ) { + uiDialog.bgiframe(); + } + + // prevent tabbing out of modal dialogs + this._on( uiDialog, { keydown: function( event ) { + if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + + var tabbables = $( ":tabbable", uiDialog ), + first = tabbables.filter( ":first" ), + last = tabbables.filter( ":last" ); + + if ( event.target === last[0] && !event.shiftKey ) { + first.focus( 1 ); + return false; + } else if ( event.target === first[0] && event.shiftKey ) { + last.focus( 1 ); + return false; + } + }}); + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + _destroy: function() { + var next, + oldPosition = this.oldPosition; + + if ( this.overlay ) { + this.overlay.destroy(); + } + this.uiDialog.hide(); + this.element + .removeClass( "ui-dialog-content ui-widget-content" ) + .hide() + .appendTo( "body" ); + this.uiDialog.remove(); + + if ( this.originalTitle ) { + this.element.attr( "title", this.originalTitle ); + } + + next = oldPosition.parent.children().eq( oldPosition.index ); + // Don't try to place the dialog next to itself (#8613) + if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { + next.before( this.element ); + } else { + oldPosition.parent.append( this.element ); + } + }, + + widget: function() { + return this.uiDialog; + }, + + close: function( event ) { + var that = this, + maxZ, thisZ; + + if ( !this._isOpen ) { + return; + } + + if ( false === this._trigger( "beforeClose", event ) ) { + return; + } + + this._isOpen = false; + + if ( this.overlay ) { + this.overlay.destroy(); + } + + if ( this.options.hide ) { + this._hide( this.uiDialog, this.options.hide, function() { + that._trigger( "close", event ); + }); + } else { + this.uiDialog.hide(); + this._trigger( "close", event ); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if ( this.options.modal ) { + maxZ = 0; + $( ".ui-dialog" ).each(function() { + if ( this !== that.uiDialog[0] ) { + thisZ = $( this ).css( "z-index" ); + if ( !isNaN( thisZ ) ) { + maxZ = Math.max( maxZ, thisZ ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return this; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function( force, event ) { + var options = this.options, + saveScroll; + + if ( ( options.modal && !force ) || + ( !options.stack && !options.modal ) ) { + return this._trigger( "focus", event ); + } + + if ( options.zIndex > $.ui.dialog.maxZ ) { + $.ui.dialog.maxZ = options.zIndex; + } + if ( this.overlay ) { + $.ui.dialog.maxZ += 1; + $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ; + this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ ); + } + + // Save and then restore scroll + // Opera 9.5+ resets when parent z-index is changed. + // http://bugs.jqueryui.com/ticket/3193 + saveScroll = { + scrollTop: this.element.scrollTop(), + scrollLeft: this.element.scrollLeft() + }; + $.ui.dialog.maxZ += 1; + this.uiDialog.css( "z-index", $.ui.dialog.maxZ ); + this.element.attr( saveScroll ); + this._trigger( "focus", event ); + + return this; + }, + + open: function() { + if ( this._isOpen ) { + return; + } + + var hasFocus, + options = this.options, + uiDialog = this.uiDialog; + + this._size(); + this._position( options.position ); + uiDialog.show( options.show ); + this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null; + this.moveToTop( true ); + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + hasFocus = this.element.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = uiDialog; + } + } + hasFocus.eq( 0 ).focus(); + + this._isOpen = true; + this._trigger( "open" ); + + return this; + }, + + _createButtons: function( buttons ) { + var that = this, + hasButtons = false; + + // if we already have a button pane, remove it + this.uiDialogButtonPane.remove(); + this.uiButtonSet.empty(); + + if ( typeof buttons === "object" && buttons !== null ) { + $.each( buttons, function() { + return !(hasButtons = true); + }); + } + if ( hasButtons ) { + $.each( buttons, function( name, props ) { + var button, click; + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + // Default to a non-submitting button + props = $.extend( { type: "button" }, props ); + // Change the context for the click callback to be the main element + click = props.click; + props.click = function() { + click.apply( that.element[0], arguments ); + }; + button = $( "", props ) + .appendTo( that.uiButtonSet ); + if ( $.fn.button ) { + button.button(); + } + }); + this.uiDialog.addClass( "ui-dialog-buttons" ); + this.uiDialogButtonPane.appendTo( this.uiDialog ); + } else { + this.uiDialog.removeClass( "ui-dialog-buttons" ); + } + }, + + _makeDraggable: function() { + var that = this, + options = this.options; + + function filteredUi( ui ) { + return { + position: ui.position, + offset: ui.offset + }; + } + + this.uiDialog.draggable({ + cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", + handle: ".ui-dialog-titlebar", + containment: "document", + start: function( event, ui ) { + $( this ) + .addClass( "ui-dialog-dragging" ); + that._trigger( "dragStart", event, filteredUi( ui ) ); + }, + drag: function( event, ui ) { + that._trigger( "drag", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + options.position = [ + ui.position.left - that.document.scrollLeft(), + ui.position.top - that.document.scrollTop() + ]; + $( this ) + .removeClass( "ui-dialog-dragging" ); + that._trigger( "dragStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function( handles ) { + handles = (handles === undefined ? this.options.resizable : handles); + var that = this, + options = this.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = this.uiDialog.css( "position" ), + resizeHandles = typeof handles === 'string' ? + handles : + "n,e,s,w,se,sw,ne,nw"; + + function filteredUi( ui ) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + this.uiDialog.resizable({ + cancel: ".ui-dialog-content", + containment: "document", + alsoResize: this.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: this._minHeight(), + handles: resizeHandles, + start: function( event, ui ) { + $( this ).addClass( "ui-dialog-resizing" ); + that._trigger( "resizeStart", event, filteredUi( ui ) ); + }, + resize: function( event, ui ) { + that._trigger( "resize", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + $( this ).removeClass( "ui-dialog-resizing" ); + options.height = $( this ).height(); + options.width = $( this ).width(); + that._trigger( "resizeStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }) + .css( "position", position ) + .find( ".ui-resizable-se" ) + .addClass( "ui-icon ui-icon-grip-diagonal-se" ); + }, + + _minHeight: function() { + var options = this.options; + + if ( options.height === "auto" ) { + return options.minHeight; + } else { + return Math.min( options.minHeight, options.height ); + } + }, + + _position: function( position ) { + var myAt = [], + offset = [ 0, 0 ], + isVisible; + + if ( position ) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); + + if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { + myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; + if ( myAt.length === 1 ) { + myAt[ 1 ] = myAt[ 0 ]; + } + + $.each( [ "left", "top" ], function( i, offsetPosition ) { + if ( +myAt[ i ] === myAt[ i ] ) { + offset[ i ] = myAt[ i ]; + myAt[ i ] = offsetPosition; + } + }); + + position = { + my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + + myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), + at: myAt.join( " " ) + }; + } + + position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is( ":visible" ); + if ( !isVisible ) { + this.uiDialog.show(); + } + this.uiDialog.position( position ); + if ( !isVisible ) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var that = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + that._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; + } + }); + + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function( key, value ) { + var isDraggable, isResizable, + uiDialog = this.uiDialog; + + switch ( key ) { + case "buttons": + this._createButtons( value ); + break; + case "closeText": + // ensure that we always pass a string + this.uiDialogTitlebarCloseText.text( "" + value ); + break; + case "dialogClass": + uiDialog + .removeClass( this.options.dialogClass ) + .addClass( uiDialogClasses + value ); + break; + case "disabled": + if ( value ) { + uiDialog.addClass( "ui-dialog-disabled" ); + } else { + uiDialog.removeClass( "ui-dialog-disabled" ); + } + break; + case "draggable": + isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + this._makeDraggable(); + } + break; + case "position": + this._position( value ); + break; + case "resizable": + // currently resizable, becoming non-resizable + isResizable = uiDialog.is( ":data(resizable)" ); + if ( isResizable && !value ) { + uiDialog.resizable( "destroy" ); + } + + // currently resizable, changing handles + if ( isResizable && typeof value === "string" ) { + uiDialog.resizable( "option", "handles", value ); + } + + // currently non-resizable, becoming resizable + if ( !isResizable && value !== false ) { + this._makeResizable( value ); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $( ".ui-dialog-title", this.uiDialogTitlebar ) + .html( "" + ( value || " " ) ); + break; + } + + this._super( key, value ); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var nonContentHeight, minContentHeight, autoHeight, + options = this.options, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: "auto", + minHeight: 0, + height: 0 + }); + + if ( options.minWidth > options.width ) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: "auto", + width: options.width + }) + .outerHeight(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); + } + } +}); + +$.extend($.ui.dialog, { + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr( "id" ); + if ( !id ) { + this.uuid += 1; + id = this.uuid; + } + return "ui-dialog-title-" + id; + }, + + overlay: function( dialog ) { + this.$el = $.ui.dialog.overlay.create( dialog ); + } +}); + +$.extend( $.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + maxZ: 0, + events: $.map( + "focus,mousedown,mouseup,keydown,keypress,click".split( "," ), + function( event ) { + return event + ".dialog-overlay"; + } + ).join( " " ), + create: function( dialog ) { + if ( this.instances.length === 0 ) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ( $.ui.dialog.overlay.instances.length ) { + $( document ).bind( $.ui.dialog.overlay.events, function( event ) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) { + return false; + } + }); + } + }, 1 ); + + // handle window resize + $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize ); + } + + var $el = ( this.oldInstances.pop() || $( "
    " ).addClass( "ui-widget-overlay" ) ); + + // allow closing by pressing the escape key + $( document ).bind( "keydown.dialog-overlay", function( event ) { + var instances = $.ui.dialog.overlay.instances; + // only react to the event if we're the top overlay + if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el && + dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + + dialog.close( event ); + event.preventDefault(); + } + }); + + $el.appendTo( document.body ).css({ + width: this.width(), + height: this.height() + }); + + if ( $.fn.bgiframe ) { + $el.bgiframe(); + } + + this.instances.push( $el ); + return $el; + }, + + destroy: function( $el ) { + var indexOf = $.inArray( $el, this.instances ), + maxZ = 0; + + if ( indexOf !== -1 ) { + this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] ); + } + + if ( this.instances.length === 0 ) { + $( [ document, window ] ).unbind( ".dialog-overlay" ); + } + + $el.height( 0 ).width( 0 ).remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + $.each( this.instances, function() { + maxZ = Math.max( maxZ, this.css( "z-index" ) ); + }); + this.maxZ = maxZ; + }, + + height: function() { + var scrollHeight, + offsetHeight; + // handle IE + if ( $.ui.ie ) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if ( scrollHeight < offsetHeight ) { + return $( window ).height() + "px"; + } else { + return scrollHeight + "px"; + } + // handle "good" browsers + } else { + return $( document ).height() + "px"; + } + }, + + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.ui.ie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if ( scrollWidth < offsetWidth ) { + return $( window ).width() + "px"; + } else { + return scrollWidth + "px"; + } + // handle "good" browsers + } else { + return $( document ).width() + "px"; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $( [] ); + $.each( $.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add( this ); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend( $.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy( this.$el ); + } +}); + +}( jQuery ) ); + +(function( $, undefined ) { + +var rvertical = /up|down|vertical/, + rpositivemotion = /up|left|vertical|horizontal/; + +$.effects.effect.blind = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + direction = o.direction || "up", + vertical = rvertical.test( direction ), + ref = vertical ? "height" : "width", + ref2 = vertical ? "top" : "left", + motion = rpositivemotion.test( direction ), + animation = {}, + show = mode === "show", + wrapper, distance, margin; + + // if already wrapped, the wrapper's properties are my property. #6245 + if ( el.parent().is( ".ui-effects-wrapper" ) ) { + $.effects.save( el.parent(), props ); + } else { + $.effects.save( el, props ); + } + el.show(); + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + distance = wrapper[ ref ](); + margin = parseFloat( wrapper.css( ref2 ) ) || 0; + + animation[ ref ] = show ? distance : 0; + if ( !motion ) { + el + .css( vertical ? "bottom" : "right", 0 ) + .css( vertical ? "top" : "left", "auto" ) + .css({ position: "absolute" }); + + animation[ ref2 ] = show ? margin : distance + margin; + } + + // start at 0 if we are showing + if ( show ) { + wrapper.css( ref, 0 ); + if ( ! motion ) { + wrapper.css( ref2, margin + distance ); + } + } + + // Animate + wrapper.animate( animation, { + duration: o.duration, + easing: o.easing, + queue: false, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.bounce = function( o, done ) { + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + + // defaults: + mode = $.effects.setMode( el, o.mode || "effect" ), + hide = mode === "hide", + show = mode === "show", + direction = o.direction || "up", + distance = o.distance, + times = o.times || 5, + + // number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = o.duration / anims, + easing = o.easing, + + // utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i, + upAnim, + downAnim, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + // Avoid touching opacity to prevent clearType and PNG issues in IE + if ( show || hide ) { + props.push( "opacity" ); + } + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); // Create Wrapper + + // default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } + + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = 0; + + // if we are showing, force opacity 0 and set the initial position + // then do the "first" animation + el.css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = 0; + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( i = 0; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + el.animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + el.animate( upAnim, speed, easing ); + } + + el.queue(function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.clip = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "vertical", + vert = direction === "vertical", + size = vert ? "height" : "width", + position = vert ? "top" : "left", + animation = {}, + wrapper, animate, distance; + + // Save & Show + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + animate = ( el[0].tagName === "IMG" ) ? wrapper : el; + distance = animate[ size ](); + + // Shift + if ( show ) { + animate.css( size, 0 ); + animate.css( position, distance / 2 ); + } + + // Create Animation Object: + animation[ size ] = show ? distance : 0; + animation[ position ] = show ? 0 : distance / 2; + + // Animate + animate.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( !show ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.drop = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", + animation = { + opacity: show ? 1 : 0 + }, + distance; + + // Adjust + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; + + if ( show ) { + el + .css( "opacity", 0 ) + .css( ref, motion === "pos" ? -distance : distance ); + } + + // Animation + animation[ ref ] = ( show ? + ( motion === "pos" ? "+=" : "-=" ) : + ( motion === "pos" ? "-=" : "+=" ) ) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.explode = function( o, done ) { + + var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, + cells = rows, + el = $( this ), + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + + // show and then visibility:hidden the element before calculating offset + offset = el.show().css( "visibility", "hidden" ).offset(), + + // width and height of a piece + width = Math.ceil( el.outerWidth() / cells ), + height = Math.ceil( el.outerHeight() / rows ), + pieces = [], + + // loop + i, j, left, top, mx, my; + + // children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // clone the element for each row and cell. + for( i = 0; i < rows ; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2 ; + + for( j = 0; j < cells ; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2 ; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + el + .clone() + .appendTo( "body" ) + .wrap( "
    " ) + .css({ + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + }) + + // select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css({ + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + }).animate({ + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, o.duration || 500, o.easing, childComplete ); + } + } + + function animComplete() { + el.css({ + visibility: "visible" + }); + $( pieces ).remove(); + if ( !show ) { + el.hide(); + } + done(); + } +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.fade = function( o, done ) { + var el = $( this ), + mode = $.effects.setMode( el, o.mode || "toggle" ); + + el.animate({ + opacity: mode + }, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: done + }); +}; + +})( jQuery ); + +(function( $, undefined ) { + +$.effects.effect.fold = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + hide = mode === "hide", + size = o.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!o.horizFirst, + widthFirst = show !== horizFirst, + ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], + duration = o.duration / 2, + wrapper, distance, + animation1 = {}, + animation2 = {}; + + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + distance = widthFirst ? + [ wrapper.width(), wrapper.height() ] : + [ wrapper.height(), wrapper.width() ]; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + if ( show ) { + wrapper.css( horizFirst ? { + height: 0, + width: size + } : { + height: size, + width: 0 + }); + } + + // Animation + animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; + animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; + + // Animate + wrapper + .animate( animation1, duration, o.easing ) + .animate( animation2, duration, o.easing, function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.highlight = function( o, done ) { + var elem = $( this ), + props = [ "backgroundImage", "backgroundColor", "opacity" ], + mode = $.effects.setMode( elem, o.mode || "show" ), + animation = { + backgroundColor: elem.css( "backgroundColor" ) + }; + + if (mode === "hide") { + animation.opacity = 0; + } + + $.effects.save( elem, props ); + + elem + .show() + .css({ + backgroundImage: "none", + backgroundColor: o.color || "#ffff99" + }) + .animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + elem.hide(); + } + $.effects.restore( elem, props ); + done(); + } + }); +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.pulsate = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "show" ), + show = mode === "show", + hide = mode === "hide", + showhide = ( show || mode === "hide" ), + + // showing or hiding leaves of the "last" animation + anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = o.duration / anims, + animateTo = 0, + queue = elem.queue(), + queuelen = queue.length, + i; + + if ( show || !elem.is(":visible")) { + elem.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // anims - 1 opacity "toggles" + for ( i = 1; i < anims; i++ ) { + elem.animate({ + opacity: animateTo + }, duration, o.easing ); + animateTo = 1 - animateTo; + } + + elem.animate({ + opacity: animateTo + }, duration, o.easing); + + elem.queue(function() { + if ( hide ) { + elem.hide(); + } + done(); + }); + + // We just queued up "anims" animations, we need to put them next in the queue + if ( queuelen > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + elem.dequeue(); +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.puff = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "hide" ), + hide = mode === "hide", + percent = parseInt( o.percent, 10 ) || 150, + factor = percent / 100, + original = { + height: elem.height(), + width: elem.width(), + outerHeight: elem.outerHeight(), + outerWidth: elem.outerWidth() + }; + + $.extend( o, { + effect: "scale", + queue: false, + fade: true, + mode: mode, + complete: done, + percent: hide ? percent : 100, + from: hide ? + original : + { + height: original.height * factor, + width: original.width * factor, + outerHeight: original.outerHeight * factor, + outerWidth: original.outerWidth * factor + } + }); + + elem.effect( o ); +}; + +$.effects.effect.scale = function( o, done ) { + + // Create element + var el = $( this ), + options = $.extend( true, {}, o ), + mode = $.effects.setMode( el, o.mode || "effect" ), + percent = parseInt( o.percent, 10 ) || + ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), + direction = o.direction || "both", + origin = o.origin, + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }, + factor = { + y: direction !== "horizontal" ? (percent / 100) : 1, + x: direction !== "vertical" ? (percent / 100) : 1 + }; + + // We are going to pass this effect to the size effect: + options.effect = "size"; + options.queue = false; + options.complete = done; + + // Set default origin and restore for show/hide + if ( mode !== "effect" ) { + options.origin = origin || ["middle","center"]; + options.restore = true; + } + + options.from = o.from || ( mode === "show" ? { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + } : original ); + options.to = { + height: original.height * factor.y, + width: original.width * factor.x, + outerHeight: original.outerHeight * factor.y, + outerWidth: original.outerWidth * factor.x + }; + + // Fade option to support puff + if ( options.fade ) { + if ( mode === "show" ) { + options.from.opacity = 0; + options.to.opacity = 1; + } + if ( mode === "hide" ) { + options.from.opacity = 1; + options.to.opacity = 0; + } + } + + // Animate + el.effect( options ); + +}; + +$.effects.effect.size = function( o, done ) { + + // Create element + var original, baseline, factor, + el = $( this ), + props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], + + // Always restore + props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], + + // Copy for children + props2 = [ "width", "height", "overflow" ], + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], + + // Set options + mode = $.effects.setMode( el, o.mode || "effect" ), + restore = o.restore || mode !== "effect", + scale = o.scale || "both", + origin = o.origin || [ "middle", "center" ], + position = el.css( "position" ), + props = restore ? props0 : props1, + zero = { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; + + if ( mode === "show" ) { + el.show(); + } + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }; + + if ( o.mode === "toggle" && mode === "show" ) { + el.from = o.to || zero; + el.to = o.from || original; + } else { + el.from = o.from || ( mode === "show" ? zero : original ); + el.to = o.to || ( mode === "hide" ? zero : original ); + } + + // Set scaling factor + factor = { + from: { + y: el.from.height / original.height, + x: el.from.width / original.width + }, + to: { + y: el.to.height / original.height, + x: el.to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( vProps ); + el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + props = props.concat( hProps ); + el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); + el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); + } + } + + // Scale the content + if ( scale === "content" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( cProps ).concat( props2 ); + el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); + } + } + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + el.css( "overflow", "hidden" ).css( el.from ); + + // Adjust + if (origin) { // Calculate baseline shifts + baseline = $.effects.getBaseline( origin, original ); + el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; + el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; + el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; + el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; + } + el.css( el.from ); // set top & left + + // Animate + if ( scale === "content" || scale === "both" ) { // Scale the children + + // Add margins/font-size + vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); + hProps = hProps.concat([ "marginLeft", "marginRight" ]); + props2 = props0.concat(vProps).concat(hProps); + + el.find( "*[width]" ).each( function(){ + var child = $( this ), + c_original = { + height: child.height(), + width: child.width(), + outerHeight: child.outerHeight(), + outerWidth: child.outerWidth() + }; + if (restore) { + $.effects.save(child, props2); + } + + child.from = { + height: c_original.height * factor.from.y, + width: c_original.width * factor.from.x, + outerHeight: c_original.outerHeight * factor.from.y, + outerWidth: c_original.outerWidth * factor.from.x + }; + child.to = { + height: c_original.height * factor.to.y, + width: c_original.width * factor.to.x, + outerHeight: c_original.height * factor.to.y, + outerWidth: c_original.width * factor.to.x + }; + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); + child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); + child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); + } + + // Animate children + child.css( child.from ); + child.animate( child.to, o.duration, o.easing, function() { + + // Restore children + if ( restore ) { + $.effects.restore( child, props2 ); + } + }); + }); + } + + // Animate + el.animate( el.to, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( el.to.opacity === 0 ) { + el.css( "opacity", el.from.opacity ); + } + if( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + if ( !restore ) { + + // we need to calculate our new positioning based on the scaling + if ( position === "static" ) { + el.css({ + position: "relative", + top: el.to.top, + left: el.to.left + }); + } else { + $.each([ "top", "left" ], function( idx, pos ) { + el.css( pos, function( _, str ) { + var val = parseInt( str, 10 ), + toRef = idx ? el.to.left : el.to.top; + + // if original was "auto", recalculate the new value from wrapper + if ( str === "auto" ) { + return toRef + "px"; + } + + return val + toRef + "px"; + }); + }); + } + } + + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.shake = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "effect" ), + direction = o.direction || "left", + distance = o.distance || 20, + times = o.times || 3, + anims = times * 2 + 1, + speed = Math.round(o.duration/anims), + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + animation = {}, + animation1 = {}, + animation2 = {}, + i, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + el.animate( animation, speed, o.easing ); + + // Shakes + for ( i = 1; i < times; i++ ) { + el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); + } + el + .animate( animation1, speed, o.easing ) + .animate( animation, speed / 2, o.easing ) + .queue(function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); + +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.slide = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "width", "height" ], + mode = $.effects.setMode( el, o.mode || "show" ), + show = mode === "show", + direction = o.direction || "left", + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + distance, + animation = {}; + + // Adjust + $.effects.save( el, props ); + el.show(); + distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); + + $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + if ( show ) { + el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); + } + + // Animation + animation[ ref ] = ( show ? + ( positiveMotion ? "+=" : "-=") : + ( positiveMotion ? "-=" : "+=")) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); +}; + +})(jQuery); + +(function( $, undefined ) { + +$.effects.effect.transfer = function( o, done ) { + var elem = $( this ), + target = $( o.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $("body"), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop , + left: endPosition.left - fixLeft , + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $( '
    ' ) + .appendTo( document.body ) + .addClass( o.className ) + .css({ + top: startPosition.top - fixTop , + left: startPosition.left - fixLeft , + height: elem.innerHeight(), + width: elem.innerWidth(), + position: targetFixed ? "fixed" : "absolute" + }) + .animate( animation, o.duration, o.easing, function() { + transfer.remove(); + done(); + }); +}; + +})(jQuery); + +(function( $, undefined ) { + +var mouseHandled = false; + +$.widget( "ui.menu", { + version: "1.9.2", + defaultElement: "
      ", + delay: 300, + options: { + icons: { + submenu: "ui-icon-carat-1-e" + }, + menus: "ul", + position: { + my: "left top", + at: "right top" + }, + role: "menu", + + // callbacks + blur: null, + focus: null, + select: null + }, + + _create: function() { + this.activeMenu = this.element; + this.element + .uniqueId() + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) + .attr({ + role: this.options.role, + tabIndex: 0 + }) + // need to catch all clicks on disabled menu + // not possible through _on + .bind( "click" + this.eventNamespace, $.proxy(function( event ) { + if ( this.options.disabled ) { + event.preventDefault(); + } + }, this )); + + if ( this.options.disabled ) { + this.element + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } + + this._on({ + // Prevent focus from sticking to links inside menu after clicking + // them (focus should always stay on UL during navigation). + "mousedown .ui-menu-item > a": function( event ) { + event.preventDefault(); + }, + "click .ui-state-disabled > a": function( event ) { + event.preventDefault(); + }, + "click .ui-menu-item:has(a)": function( event ) { + var target = $( event.target ).closest( ".ui-menu-item" ); + if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) { + mouseHandled = true; + + this.select( event ); + // Open submenu on click + if ( target.has( ".ui-menu" ).length ) { + this.expand( event ); + } else if ( !this.element.is( ":focus" ) ) { + // Redirect focus to the menu + this.element.trigger( "focus", [ true ] ); + + // If the active item is on the top level, let it stay active. + // Otherwise, blur the active item since it is no longer visible. + if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { + clearTimeout( this.timer ); + } + } + } + }, + "mouseenter .ui-menu-item": function( event ) { + var target = $( event.currentTarget ); + // Remove ui-state-active class from siblings of the newly focused menu item + // to avoid a jump caused by adjacent elements both having a class with a border + target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); + this.focus( event, target ); + }, + mouseleave: "collapseAll", + "mouseleave .ui-menu": "collapseAll", + focus: function( event, keepActiveItem ) { + // If there's already an active item, keep it active + // If not, activate the first item + var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); + + if ( !keepActiveItem ) { + this.focus( event, item ); + } + }, + blur: function( event ) { + this._delay(function() { + if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { + this.collapseAll( event ); + } + }); + }, + keydown: "_keydown" + }); + + this.refresh(); + + // Clicks outside of a menu collapse any open menus + this._on( this.document, { + click: function( event ) { + if ( !$( event.target ).closest( ".ui-menu" ).length ) { + this.collapseAll( event ); + } + + // Reset the mouseHandled flag + mouseHandled = false; + } + }); + }, + + _destroy: function() { + // Destroy (sub)menus + this.element + .removeAttr( "aria-activedescendant" ) + .find( ".ui-menu" ).andSelf() + .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-disabled" ) + .removeUniqueId() + .show(); + + // Destroy menu items + this.element.find( ".ui-menu-item" ) + .removeClass( "ui-menu-item" ) + .removeAttr( "role" ) + .removeAttr( "aria-disabled" ) + .children( "a" ) + .removeUniqueId() + .removeClass( "ui-corner-all ui-state-hover" ) + .removeAttr( "tabIndex" ) + .removeAttr( "role" ) + .removeAttr( "aria-haspopup" ) + .children().each( function() { + var elem = $( this ); + if ( elem.data( "ui-menu-submenu-carat" ) ) { + elem.remove(); + } + }); + + // Destroy menu dividers + this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); + }, + + _keydown: function( event ) { + var match, prev, character, skip, regex, + preventDefault = true; + + function escape( value ) { + return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.PAGE_UP: + this.previousPage( event ); + break; + case $.ui.keyCode.PAGE_DOWN: + this.nextPage( event ); + break; + case $.ui.keyCode.HOME: + this._move( "first", "first", event ); + break; + case $.ui.keyCode.END: + this._move( "last", "last", event ); + break; + case $.ui.keyCode.UP: + this.previous( event ); + break; + case $.ui.keyCode.DOWN: + this.next( event ); + break; + case $.ui.keyCode.LEFT: + this.collapse( event ); + break; + case $.ui.keyCode.RIGHT: + if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { + this.expand( event ); + } + break; + case $.ui.keyCode.ENTER: + case $.ui.keyCode.SPACE: + this._activate( event ); + break; + case $.ui.keyCode.ESCAPE: + this.collapse( event ); + break; + default: + preventDefault = false; + prev = this.previousFilter || ""; + character = String.fromCharCode( event.keyCode ); + skip = false; + + clearTimeout( this.filterTimer ); + + if ( character === prev ) { + skip = true; + } else { + character = prev + character; + } + + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); + }); + match = skip && match.index( this.active.next() ) !== -1 ? + this.active.nextAll( ".ui-menu-item" ) : + match; + + // If no matches on the current filter, reset to the last character pressed + // to move down the menu to the first item that starts with that character + if ( !match.length ) { + character = String.fromCharCode( event.keyCode ); + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); + }); + } + + if ( match.length ) { + this.focus( event, match ); + if ( match.length > 1 ) { + this.previousFilter = character; + this.filterTimer = this._delay(function() { + delete this.previousFilter; + }, 1000 ); + } else { + delete this.previousFilter; + } + } else { + delete this.previousFilter; + } + } + + if ( preventDefault ) { + event.preventDefault(); + } + }, + + _activate: function( event ) { + if ( !this.active.is( ".ui-state-disabled" ) ) { + if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + this.expand( event ); + } else { + this.select( event ); + } + } + }, + + refresh: function() { + var menus, + icon = this.options.icons.submenu, + submenus = this.element.find( this.options.menus ); + + // Initialize nested menus + submenus.filter( ":not(.ui-menu)" ) + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .hide() + .attr({ + role: this.options.role, + "aria-hidden": "true", + "aria-expanded": "false" + }) + .each(function() { + var menu = $( this ), + item = menu.prev( "a" ), + submenuCarat = $( "" ) + .addClass( "ui-menu-icon ui-icon " + icon ) + .data( "ui-menu-submenu-carat", true ); + + item + .attr( "aria-haspopup", "true" ) + .prepend( submenuCarat ); + menu.attr( "aria-labelledby", item.attr( "id" ) ); + }); + + menus = submenus.add( this.element ); + + // Don't refresh list items that are already adapted + menus.children( ":not(.ui-menu-item):has(a)" ) + .addClass( "ui-menu-item" ) + .attr( "role", "presentation" ) + .children( "a" ) + .uniqueId() + .addClass( "ui-corner-all" ) + .attr({ + tabIndex: -1, + role: this._itemRole() + }); + + // Initialize unlinked menu-items containing spaces and/or dashes only as dividers + menus.children( ":not(.ui-menu-item)" ).each(function() { + var item = $( this ); + // hyphen, em dash, en dash + if ( !/[^\-—–\s]/.test( item.text() ) ) { + item.addClass( "ui-widget-content ui-menu-divider" ); + } + }); + + // Add aria-disabled attribute to any disabled menu item + menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); + + // If the active item has been removed, blur the menu + if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + this.blur(); + } + }, + + _itemRole: function() { + return { + menu: "menuitem", + listbox: "option" + }[ this.options.role ]; + }, + + focus: function( event, item ) { + var nested, focused; + this.blur( event, event && event.type === "focus" ); + + this._scrollIntoView( item ); + + this.active = item.first(); + focused = this.active.children( "a" ).addClass( "ui-state-focus" ); + // Only update aria-activedescendant if there's a role + // otherwise we assume focus is managed elsewhere + if ( this.options.role ) { + this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); + } + + // Highlight active parent menu item, if any + this.active + .parent() + .closest( ".ui-menu-item" ) + .children( "a:first" ) + .addClass( "ui-state-active" ); + + if ( event && event.type === "keydown" ) { + this._close(); + } else { + this.timer = this._delay(function() { + this._close(); + }, this.delay ); + } + + nested = item.children( ".ui-menu" ); + if ( nested.length && ( /^mouse/.test( event.type ) ) ) { + this._startOpening(nested); + } + this.activeMenu = item.parent(); + + this._trigger( "focus", event, { item: item } ); + }, + + _scrollIntoView: function( item ) { + var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + if ( this._hasScroll() ) { + borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; + paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; + offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; + scroll = this.activeMenu.scrollTop(); + elementHeight = this.activeMenu.height(); + itemHeight = item.height(); + + if ( offset < 0 ) { + this.activeMenu.scrollTop( scroll + offset ); + } else if ( offset + itemHeight > elementHeight ) { + this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); + } + } + }, + + blur: function( event, fromFocus ) { + if ( !fromFocus ) { + clearTimeout( this.timer ); + } + + if ( !this.active ) { + return; + } + + this.active.children( "a" ).removeClass( "ui-state-focus" ); + this.active = null; + + this._trigger( "blur", event, { item: this.active } ); + }, + + _startOpening: function( submenu ) { + clearTimeout( this.timer ); + + // Don't open if already open fixes a Firefox bug that caused a .5 pixel + // shift in the submenu position when mousing over the carat icon + if ( submenu.attr( "aria-hidden" ) !== "true" ) { + return; + } + + this.timer = this._delay(function() { + this._close(); + this._open( submenu ); + }, this.delay ); + }, + + _open: function( submenu ) { + var position = $.extend({ + of: this.active + }, this.options.position ); + + clearTimeout( this.timer ); + this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) + .hide() + .attr( "aria-hidden", "true" ); + + submenu + .show() + .removeAttr( "aria-hidden" ) + .attr( "aria-expanded", "true" ) + .position( position ); + }, + + collapseAll: function( event, all ) { + clearTimeout( this.timer ); + this.timer = this._delay(function() { + // If we were passed an event, look for the submenu that contains the event + var currentMenu = all ? this.element : + $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); + + // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway + if ( !currentMenu.length ) { + currentMenu = this.element; + } + + this._close( currentMenu ); + + this.blur( event ); + this.activeMenu = currentMenu; + }, this.delay ); + }, + + // With no arguments, closes the currently active menu - if nothing is active + // it closes all menus. If passed an argument, it will search for menus BELOW + _close: function( startMenu ) { + if ( !startMenu ) { + startMenu = this.active ? this.active.parent() : this.element; + } + + startMenu + .find( ".ui-menu" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .end() + .find( "a.ui-state-active" ) + .removeClass( "ui-state-active" ); + }, + + collapse: function( event ) { + var newItem = this.active && + this.active.parent().closest( ".ui-menu-item", this.element ); + if ( newItem && newItem.length ) { + this._close(); + this.focus( event, newItem ); + } + }, + + expand: function( event ) { + var newItem = this.active && + this.active + .children( ".ui-menu " ) + .children( ".ui-menu-item" ) + .first(); + + if ( newItem && newItem.length ) { + this._open( newItem.parent() ); + + // Delay so Firefox will not hide activedescendant change in expanding submenu from AT + this._delay(function() { + this.focus( event, newItem ); + }); + } + }, + + next: function( event ) { + this._move( "next", "first", event ); + }, + + previous: function( event ) { + this._move( "prev", "last", event ); + }, + + isFirstItem: function() { + return this.active && !this.active.prevAll( ".ui-menu-item" ).length; + }, + + isLastItem: function() { + return this.active && !this.active.nextAll( ".ui-menu-item" ).length; + }, + + _move: function( direction, filter, event ) { + var next; + if ( this.active ) { + if ( direction === "first" || direction === "last" ) { + next = this.active + [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) + .eq( -1 ); + } else { + next = this.active + [ direction + "All" ]( ".ui-menu-item" ) + .eq( 0 ); + } + } + if ( !next || !next.length || !this.active ) { + next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); + } + + this.focus( event, next ); + }, + + nextPage: function( event ) { + var item, base, height; + + if ( !this.active ) { + this.next( event ); + return; + } + if ( this.isLastItem() ) { + return; + } + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.nextAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base - height < 0; + }); + + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ) + [ !this.active ? "first" : "last" ]() ); + } + }, + + previousPage: function( event ) { + var item, base, height; + if ( !this.active ) { + this.next( event ); + return; + } + if ( this.isFirstItem() ) { + return; + } + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.prevAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base + height > 0; + }); + + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + } + }, + + _hasScroll: function() { + return this.element.outerHeight() < this.element.prop( "scrollHeight" ); + }, + + select: function( event ) { + // TODO: It should never be possible to not have an active item at this + // point, but the tests don't trigger mouseenter before click. + this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); + var ui = { item: this.active }; + if ( !this.active.has( ".ui-menu" ).length ) { + this.collapseAll( event, true ); + } + this._trigger( "select", event, ui ); + } +}); + +}( jQuery )); + +(function( $, undefined ) { + +$.ui = $.ui || {}; + +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + round = Math.round, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} + +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "
      " ), + innerDiv = div.children()[0]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[0].clientWidth; + } + + div.remove(); + + return (cachedScrollbarWidth = w1 - w2); + }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ), + overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); + return { + width: hasOverflowX ? $.position.scrollbarWidth() : 0, + height: hasOverflowY ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isWindow = $.isWindow( withinElement[0] ); + return { + element: withinElement, + isWindow: isWindow, + offset: withinElement.offset() || { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: isWindow ? withinElement.width() : withinElement.outerWidth(), + height: isWindow ? withinElement.height() : withinElement.outerHeight() + }; + } +}; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, + target = $( options.of ), + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; + + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: 0, left: 0 }; + } else if ( $.isWindow( targetElem ) ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + targetOffset = { top: targetElem.pageY, left: targetElem.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + targetOffset = target.offset(); + } + // clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); + + // force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; + + if ( pos.length === 1) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; + + // reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + }); + + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } + + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; + + return this.each(function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); + + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; + } + + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } + + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; + + // if the browser doesn't support fractions, then round for consistent results + if ( !$.support.offsetFractions ) { + position.left = round( position.left ); + position.top = round( position.top ); + } + + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem : elem + }); + } + }); + + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } + + if ( options.using ) { + // adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; + } + + elem.offset( $.extend( position, { using: using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // element is wider than within + if ( data.collisionWidth > outerWidth ) { + // element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; + position.left += overLeft - newOverRight; + // element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + // element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } + } + // too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + // too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + // adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // element is taller than within + if ( data.collisionHeight > outerHeight ) { + // element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; + position.top += overTop - newOverBottom; + // element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + // element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + // too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + // too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + // adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); + } + } + }, + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } + else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; + if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { + position.top += myOffset + atOffset + offset; + } + } + else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; + if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { + position.top += myOffset + atOffset + offset; + } + } + } + }, + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); + } + } +}; + +// fraction support test +(function () { + var testElement, testElementParent, testElementStyle, offsetLeft, i, + body = document.getElementsByTagName( "body" )[ 0 ], + div = document.createElement( "div" ); + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + $.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || document.documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + div.style.cssText = "position: absolute; left: 10.7432222px;"; + + offsetLeft = $( div ).offset().left; + $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; + + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); +})(); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // offset option + (function( $ ) { + var _position = $.fn.position; + $.fn.position = function( options ) { + if ( !options || !options.offset ) { + return _position.call( this, options ); + } + var offset = options.offset.split( " " ), + at = options.at.split( " " ); + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + if ( /^\d/.test( offset[ 0 ] ) ) { + offset[ 0 ] = "+" + offset[ 0 ]; + } + if ( /^\d/.test( offset[ 1 ] ) ) { + offset[ 1 ] = "+" + offset[ 1 ]; + } + if ( at.length === 1 ) { + if ( /left|center|right/.test( at[ 0 ] ) ) { + at[ 1 ] = "center"; + } else { + at[ 1 ] = at[ 0 ]; + at[ 0 ] = "center"; + } + } + return _position.call( this, $.extend( options, { + at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ], + offset: undefined + } ) ); + }; + }( jQuery ) ); +} + +}( jQuery ) ); + +(function( $, undefined ) { + +$.widget( "ui.progressbar", { + version: "1.9.2", + options: { + value: 0, + max: 100 + }, + + min: 0, + + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); + + this.valueDiv = $( "
      " ) + .appendTo( this.element ); + + this.oldValue = this._value(); + this._refreshValue(); + }, + + _destroy: function() { + this.element + .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + + this.valueDiv.remove(); + }, + + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); + } + + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); + } + } + + this._super( key, value ); + }, + + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; + } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, + + _percentage: function() { + return 100 * this._value() / this.options.max; + }, + + _refreshValue: function() { + var value = this.value(), + percentage = this._percentage(); + + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); + } + + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); + +})( jQuery ); + +(function( $, undefined ) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; + +$.widget( "ui.slider", $.ui.mouse, { + version: "1.9.2", + widgetEventPrefix: "slide", + + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null + }, + + _create: function() { + var i, handleCount, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "", + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); + + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $( "
      " ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); + } + + handleCount = ( o.values && o.values.length ) || 1; + + for ( i = existingHandles.length; i < handleCount; i++ ) { + handles.push( handle ); + } + + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); + + this.handle = this.handles.eq( 0 ); + + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .mouseenter(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }) + .mouseleave(function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); + + this.handles.each(function( i ) { + $( this ).data( "ui-slider-handle-index", i ); + }); + + this._on( this.handles, { + keydown: function( event ) { + var allowed, curVal, newVal, step, + index = $( event.target ).data( "ui-slider-handle-index" ); + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if ( !this._keySliding ) { + this._keySliding = true; + $( event.target ).addClass( "ui-state-active" ); + allowed = this._start( event, index ); + if ( allowed === false ) { + return; + } + } + break; + } + + step = this.options.step; + if ( this.options.values && this.options.values.length ) { + curVal = newVal = this.values( index ); + } else { + curVal = newVal = this.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = this._valueMin(); + break; + case $.ui.keyCode.END: + newVal = this._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === this._valueMax() ) { + return; + } + newVal = this._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === this._valueMin() ) { + return; + } + newVal = this._trimAlignValue( curVal - step ); + break; + } + + this._slide( event, index, newVal ); + }, + keyup: function( event ) { + var index = $( event.target ).data( "ui-slider-handle-index" ); + + if ( this._keySliding ) { + this._keySliding = false; + this._stop( event, index ); + this._change( event, index ); + $( event.target ).removeClass( "ui-state-active" ); + } + } + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + _destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ); + + this._mouseDestroy(); + }, + + _mouseCapture: function( event ) { + var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, + that = this, + o = this.options; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - that.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); + } + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; + } + this._mouseSliding = true; + + this._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); + } + this._animateOff = true; + return true; + }, + + _mouseStart: function() { + return true; + }, + + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; + } + if ( percentMouse < 0 ) { + percentMouse = 0; + } + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); + }, + + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); + } + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } + } + }, + + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "stop", event, uiHash ); + }, + + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "change", event, uiHash ); + } + }, + + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); + return; + } + + return this._value(); + }, + + values: function( index, newValue ) { + var vals, + newValues, + i; + + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); + return; + } + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.prop( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.prop( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass( "ui-slider-horizontal ui-slider-vertical" ) + .addClass( "ui-slider-" + this.orientation ); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + case "min": + case "max": + this._animateOff = true; + this._refreshValue(); + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); + } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); + }, + + _valueMin: function() { + return this.options.min; + }, + + _valueMax: function() { + return this.options.max; + }, + + _refreshValue: function() { + var lastValPercent, valPercent, value, valueMin, valueMax, + oRange = this.options.range, + o = this.options, + that = this, + animate = ( !this._animateOff ) ? o.animate : false, + _set = {}; + + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i ) { + valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; + _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( that.options.range === true ) { + if ( that.orientation === "horizontal" ) { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + +}); + +}(jQuery)); + +(function( $ ) { + +function modifier( fn ) { + return function() { + var previous = this.element.val(); + fn.apply( this, arguments ); + this._refresh(); + if ( previous !== this.element.val() ) { + this._trigger( "change" ); + } + }; +} + +$.widget( "ui.spinner", { + version: "1.9.2", + defaultElement: "", + widgetEventPrefix: "spin", + options: { + culture: null, + icons: { + down: "ui-icon-triangle-1-s", + up: "ui-icon-triangle-1-n" + }, + incremental: true, + max: null, + min: null, + numberFormat: null, + page: 10, + step: 1, + + change: null, + spin: null, + start: null, + stop: null + }, + + _create: function() { + // handle string values that need to be parsed + this._setOption( "max", this.options.max ); + this._setOption( "min", this.options.min ); + this._setOption( "step", this.options.step ); + + // format the value, but don't constrain + this._value( this.element.val(), true ); + + this._draw(); + this._on( this._events ); + this._refresh(); + + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + this._on( this.window, { + beforeunload: function() { + this.element.removeAttr( "autocomplete" ); + } + }); + }, + + _getCreateOptions: function() { + var options = {}, + element = this.element; + + $.each( [ "min", "max", "step" ], function( i, option ) { + var value = element.attr( option ); + if ( value !== undefined && value.length ) { + options[ option ] = value; + } + }); + + return options; + }, + + _events: { + keydown: function( event ) { + if ( this._start( event ) && this._keydown( event ) ) { + event.preventDefault(); + } + }, + keyup: "_stop", + focus: function() { + this.previous = this.element.val(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } + + this._refresh(); + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event ); + } + }, + mousewheel: function( event, delta ) { + if ( !delta ) { + return; + } + if ( !this.spinning && !this._start( event ) ) { + return false; + } + + this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); + clearTimeout( this.mousewheelTimer ); + this.mousewheelTimer = this._delay(function() { + if ( this.spinning ) { + this._stop( event ); + } + }, 100 ); + event.preventDefault(); + }, + "mousedown .ui-spinner-button": function( event ) { + var previous; + + // We never want the buttons to have focus; whenever the user is + // interacting with the spinner, the focus should be on the input. + // If the input is focused then this.previous is properly set from + // when the input first received focus. If the input is not focused + // then we need to set this.previous based on the value before spinning. + previous = this.element[0] === this.document[0].activeElement ? + this.previous : this.element.val(); + function checkFocus() { + var isActive = this.element[0] === this.document[0].activeElement; + if ( !isActive ) { + this.element.focus(); + this.previous = previous; + // support: IE + // IE sets focus asynchronously, so we need to check if focus + // moved off of the input because the user clicked on the button. + this._delay(function() { + this.previous = previous; + }); + } + } + + // ensure focus is on (or stays on) the text field + event.preventDefault(); + checkFocus.call( this ); + + // support: IE + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + // and check (again) if focus moved off of the input. + this.cancelBlur = true; + this._delay(function() { + delete this.cancelBlur; + checkFocus.call( this ); + }); + + if ( this._start( event ) === false ) { + return; + } + + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + "mouseup .ui-spinner-button": "_stop", + "mouseenter .ui-spinner-button": function( event ) { + // button will add ui-state-active if mouse was down while mouseleave and kept down + if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { + return; + } + + if ( this._start( event ) === false ) { + return false; + } + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + // TODO: do we really want to consider this a stop? + // shouldn't we just stop the repeater and wait until mouseup before + // we trigger the stop event? + "mouseleave .ui-spinner-button": "_stop" + }, + + _draw: function() { + var uiSpinner = this.uiSpinner = this.element + .addClass( "ui-spinner-input" ) + .attr( "autocomplete", "off" ) + .wrap( this._uiSpinnerHtml() ) + .parent() + // add buttons + .append( this._buttonHtml() ); + + this.element.attr( "role", "spinbutton" ); + + // button bindings + this.buttons = uiSpinner.find( ".ui-spinner-button" ) + .attr( "tabIndex", -1 ) + .button() + .removeClass( "ui-corner-all" ); + + // IE 6 doesn't understand height: 50% for the buttons + // unless the wrapper has an explicit height + if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && + uiSpinner.height() > 0 ) { + uiSpinner.height( uiSpinner.height() ); + } + + // disable spinner if element was already disabled + if ( this.options.disabled ) { + this.disable(); + } + }, + + _keydown: function( event ) { + var options = this.options, + keyCode = $.ui.keyCode; + + switch ( event.keyCode ) { + case keyCode.UP: + this._repeat( null, 1, event ); + return true; + case keyCode.DOWN: + this._repeat( null, -1, event ); + return true; + case keyCode.PAGE_UP: + this._repeat( null, options.page, event ); + return true; + case keyCode.PAGE_DOWN: + this._repeat( null, -options.page, event ); + return true; + } + + return false; + }, + + _uiSpinnerHtml: function() { + return ""; + }, + + _buttonHtml: function() { + return "" + + "" + + "" + + "" + + "" + + "" + + ""; + }, + + _start: function( event ) { + if ( !this.spinning && this._trigger( "start", event ) === false ) { + return false; + } + + if ( !this.counter ) { + this.counter = 1; + } + this.spinning = true; + return true; + }, + + _repeat: function( i, steps, event ) { + i = i || 500; + + clearTimeout( this.timer ); + this.timer = this._delay(function() { + this._repeat( 40, steps, event ); + }, i ); + + this._spin( steps * this.options.step, event ); + }, + + _spin: function( step, event ) { + var value = this.value() || 0; + + if ( !this.counter ) { + this.counter = 1; + } + + value = this._adjustValue( value + step * this._increment( this.counter ) ); + + if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { + this._value( value ); + this.counter++; + } + }, + + _increment: function( i ) { + var incremental = this.options.incremental; + + if ( incremental ) { + return $.isFunction( incremental ) ? + incremental( i ) : + Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); + } + + return 1; + }, + + _precision: function() { + var precision = this._precisionOf( this.options.step ); + if ( this.options.min !== null ) { + precision = Math.max( precision, this._precisionOf( this.options.min ) ); + } + return precision; + }, + + _precisionOf: function( num ) { + var str = num.toString(), + decimal = str.indexOf( "." ); + return decimal === -1 ? 0 : str.length - decimal - 1; + }, + + _adjustValue: function( value ) { + var base, aboveMin, + options = this.options; + + // make sure we're at a valid step + // - find out where we are relative to the base (min or 0) + base = options.min !== null ? options.min : 0; + aboveMin = value - base; + // - round to the nearest step + aboveMin = Math.round(aboveMin / options.step) * options.step; + // - rounding is based on 0, so adjust back to our base + value = base + aboveMin; + + // fix precision from bad JS floating point math + value = parseFloat( value.toFixed( this._precision() ) ); + + // clamp the value + if ( options.max !== null && value > options.max) { + return options.max; + } + if ( options.min !== null && value < options.min ) { + return options.min; + } + + return value; + }, + + _stop: function( event ) { + if ( !this.spinning ) { + return; + } + + clearTimeout( this.timer ); + clearTimeout( this.mousewheelTimer ); + this.counter = 0; + this.spinning = false; + this._trigger( "stop", event ); + }, + + _setOption: function( key, value ) { + if ( key === "culture" || key === "numberFormat" ) { + var prevValue = this._parse( this.element.val() ); + this.options[ key ] = value; + this.element.val( this._format( prevValue ) ); + return; + } + + if ( key === "max" || key === "min" || key === "step" ) { + if ( typeof value === "string" ) { + value = this._parse( value ); + } + } + + this._super( key, value ); + + if ( key === "disabled" ) { + if ( value ) { + this.element.prop( "disabled", true ); + this.buttons.button( "disable" ); + } else { + this.element.prop( "disabled", false ); + this.buttons.button( "enable" ); + } + } + }, + + _setOptions: modifier(function( options ) { + this._super( options ); + this._value( this.element.val() ); + }), + + _parse: function( val ) { + if ( typeof val === "string" && val !== "" ) { + val = window.Globalize && this.options.numberFormat ? + Globalize.parseFloat( val, 10, this.options.culture ) : +val; + } + return val === "" || isNaN( val ) ? null : val; + }, + + _format: function( value ) { + if ( value === "" ) { + return ""; + } + return window.Globalize && this.options.numberFormat ? + Globalize.format( value, this.options.numberFormat, this.options.culture ) : + value; + }, + + _refresh: function() { + this.element.attr({ + "aria-valuemin": this.options.min, + "aria-valuemax": this.options.max, + // TODO: what should we do with values that can't be parsed? + "aria-valuenow": this._parse( this.element.val() ) + }); + }, + + // update the value without triggering change + _value: function( value, allowAny ) { + var parsed; + if ( value !== "" ) { + parsed = this._parse( value ); + if ( parsed !== null ) { + if ( !allowAny ) { + parsed = this._adjustValue( parsed ); + } + value = this._format( parsed ); + } + } + this.element.val( value ); + this._refresh(); + }, + + _destroy: function() { + this.element + .removeClass( "ui-spinner-input" ) + .prop( "disabled", false ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + this.uiSpinner.replaceWith( this.element ); + }, + + stepUp: modifier(function( steps ) { + this._stepUp( steps ); + }), + _stepUp: function( steps ) { + this._spin( (steps || 1) * this.options.step ); + }, + + stepDown: modifier(function( steps ) { + this._stepDown( steps ); + }), + _stepDown: function( steps ) { + this._spin( (steps || 1) * -this.options.step ); + }, + + pageUp: modifier(function( pages ) { + this._stepUp( (pages || 1) * this.options.page ); + }), + + pageDown: modifier(function( pages ) { + this._stepDown( (pages || 1) * this.options.page ); + }), + + value: function( newVal ) { + if ( !arguments.length ) { + return this._parse( this.element.val() ); + } + modifier( this._value ).call( this, newVal ); + }, + + widget: function() { + return this.uiSpinner; + } +}); + +}( jQuery ) ); + +(function( $, undefined ) { + +var tabId = 0, + rhash = /#.*$/; + +function getNextTabId() { + return ++tabId; +} + +function isLocal( anchor ) { + return anchor.hash.length > 1 && + anchor.href.replace( rhash, "" ) === + location.href.replace( rhash, "" ) + // support: Safari 5.1 + // Safari 5.1 doesn't encode spaces in window.location + // but it does encode spaces from anchors (#8777) + .replace( /\s/g, "%20" ); +} + +$.widget( "ui.tabs", { + version: "1.9.2", + delay: 300, + options: { + active: null, + collapsible: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + load: null + }, + + _create: function() { + var that = this, + options = this.options, + active = options.active, + locationHash = location.hash.substring( 1 ); + + this.running = false; + + this.element + .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-tabs-collapsible", options.collapsible ) + // Prevent users from focusing disabled tabs via click + .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { + if ( $( this ).is( ".ui-state-disabled" ) ) { + event.preventDefault(); + } + }) + // support: IE <9 + // Preventing the default action in mousedown doesn't prevent IE + // from focusing the element, so if the anchor gets focused, blur. + // We don't have to worry about focusing the previously focused + // element since clicking on a non-focusable element should focus + // the body anyway. + .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { + if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { + this.blur(); + } + }); + + this._processTabs(); + + if ( active === null ) { + // check the fragment identifier in the URL + if ( locationHash ) { + this.tabs.each(function( i, tab ) { + if ( $( tab ).attr( "aria-controls" ) === locationHash ) { + active = i; + return false; + } + }); + } + + // check for a tab marked active via a class + if ( active === null ) { + active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); + } + + // no active tab, set to false + if ( active === null || active === -1 ) { + active = this.tabs.length ? 0 : false; + } + } + + // handle numbers: negative, out of range + if ( active !== false ) { + active = this.tabs.index( this.tabs.eq( active ) ); + if ( active === -1 ) { + active = options.collapsible ? false : 0; + } + } + options.active = active; + + // don't allow collapsible: false and active: false + if ( !options.collapsible && options.active === false && this.anchors.length ) { + options.active = 0; + } + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( $.isArray( options.disabled ) ) { + options.disabled = $.unique( options.disabled.concat( + $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { + return that.tabs.index( li ); + }) + ) ).sort(); + } + + // check for length avoids error when initializing empty list + if ( this.options.active !== false && this.anchors.length ) { + this.active = this._findActive( this.options.active ); + } else { + this.active = $(); + } + + this._refresh(); + + if ( this.active.length ) { + this.load( options.active ); + } + }, + + _getCreateEventData: function() { + return { + tab: this.active, + panel: !this.active.length ? $() : this._getPanelForTab( this.active ) + }; + }, + + _tabKeydown: function( event ) { + var focusedTab = $( this.document[0].activeElement ).closest( "li" ), + selectedIndex = this.tabs.index( focusedTab ), + goingForward = true; + + if ( this._handlePageNav( event ) ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + selectedIndex++; + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.LEFT: + goingForward = false; + selectedIndex--; + break; + case $.ui.keyCode.END: + selectedIndex = this.anchors.length - 1; + break; + case $.ui.keyCode.HOME: + selectedIndex = 0; + break; + case $.ui.keyCode.SPACE: + // Activate only, no collapsing + event.preventDefault(); + clearTimeout( this.activating ); + this._activate( selectedIndex ); + return; + case $.ui.keyCode.ENTER: + // Toggle (cancel delayed activation, allow collapsing) + event.preventDefault(); + clearTimeout( this.activating ); + // Determine if we should collapse or activate + this._activate( selectedIndex === this.options.active ? false : selectedIndex ); + return; + default: + return; + } + + // Focus the appropriate tab, based on which key was pressed + event.preventDefault(); + clearTimeout( this.activating ); + selectedIndex = this._focusNextTab( selectedIndex, goingForward ); + + // Navigating with control key will prevent automatic activation + if ( !event.ctrlKey ) { + // Update aria-selected immediately so that AT think the tab is already selected. + // Otherwise AT may confuse the user by stating that they need to activate the tab, + // but the tab will already be activated by the time the announcement finishes. + focusedTab.attr( "aria-selected", "false" ); + this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); + + this.activating = this._delay(function() { + this.option( "active", selectedIndex ); + }, this.delay ); + } + }, + + _panelKeydown: function( event ) { + if ( this._handlePageNav( event ) ) { + return; + } + + // Ctrl+up moves focus to the current tab + if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { + event.preventDefault(); + this.active.focus(); + } + }, + + // Alt+page up/down moves focus to the previous/next tab (and activates) + _handlePageNav: function( event ) { + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { + this._activate( this._focusNextTab( this.options.active - 1, false ) ); + return true; + } + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { + this._activate( this._focusNextTab( this.options.active + 1, true ) ); + return true; + } + }, + + _findNextTab: function( index, goingForward ) { + var lastTabIndex = this.tabs.length - 1; + + function constrain() { + if ( index > lastTabIndex ) { + index = 0; + } + if ( index < 0 ) { + index = lastTabIndex; + } + return index; + } + + while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { + index = goingForward ? index + 1 : index - 1; + } + + return index; + }, + + _focusNextTab: function( index, goingForward ) { + index = this._findNextTab( index, goingForward ); + this.tabs.eq( index ).focus(); + return index; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "disabled" ) { + // don't use the widget factory's disabled handling + this._setupDisabled( value ); + return; + } + + this._super( key, value); + + if ( key === "collapsible" ) { + this.element.toggleClass( "ui-tabs-collapsible", value ); + // Setting collapsible: false while collapsed; open first panel + if ( !value && this.options.active === false ) { + this._activate( 0 ); + } + } + + if ( key === "event" ) { + this._setupEvents( value ); + } + + if ( key === "heightStyle" ) { + this._setupHeightStyle( value ); + } + }, + + _tabId: function( tab ) { + return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); + }, + + _sanitizeSelector: function( hash ) { + return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; + }, + + refresh: function() { + var options = this.options, + lis = this.tablist.children( ":has(a[href])" ); + + // get disabled tabs from class attribute from HTML + // this will get converted to a boolean if needed in _refresh() + options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { + return lis.index( tab ); + }); + + this._processTabs(); + + // was collapsed or no tabs + if ( options.active === false || !this.anchors.length ) { + options.active = false; + this.active = $(); + // was active, but active tab is gone + } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { + // all remaining tabs are disabled + if ( this.tabs.length === options.disabled.length ) { + options.active = false; + this.active = $(); + // activate previous tab + } else { + this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); + } + // was active, active tab still exists + } else { + // make sure active index is correct + options.active = this.tabs.index( this.active ); + } + + this._refresh(); + }, + + _refresh: function() { + this._setupDisabled( this.options.disabled ); + this._setupEvents( this.options.event ); + this._setupHeightStyle( this.options.heightStyle ); + + this.tabs.not( this.active ).attr({ + "aria-selected": "false", + tabIndex: -1 + }); + this.panels.not( this._getPanelForTab( this.active ) ) + .hide() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + + // Make sure one tab is in the tab order + if ( !this.active.length ) { + this.tabs.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active + .addClass( "ui-tabs-active ui-state-active" ) + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + this._getPanelForTab( this.active ) + .show() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + } + }, + + _processTabs: function() { + var that = this; + + this.tablist = this._getList() + .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .attr( "role", "tablist" ); + + this.tabs = this.tablist.find( "> li:has(a[href])" ) + .addClass( "ui-state-default ui-corner-top" ) + .attr({ + role: "tab", + tabIndex: -1 + }); + + this.anchors = this.tabs.map(function() { + return $( "a", this )[ 0 ]; + }) + .addClass( "ui-tabs-anchor" ) + .attr({ + role: "presentation", + tabIndex: -1 + }); + + this.panels = $(); + + this.anchors.each(function( i, anchor ) { + var selector, panel, panelId, + anchorId = $( anchor ).uniqueId().attr( "id" ), + tab = $( anchor ).closest( "li" ), + originalAriaControls = tab.attr( "aria-controls" ); + + // inline tab + if ( isLocal( anchor ) ) { + selector = anchor.hash; + panel = that.element.find( that._sanitizeSelector( selector ) ); + // remote tab + } else { + panelId = that._tabId( tab ); + selector = "#" + panelId; + panel = that.element.find( selector ); + if ( !panel.length ) { + panel = that._createPanel( panelId ); + panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); + } + panel.attr( "aria-live", "polite" ); + } + + if ( panel.length) { + that.panels = that.panels.add( panel ); + } + if ( originalAriaControls ) { + tab.data( "ui-tabs-aria-controls", originalAriaControls ); + } + tab.attr({ + "aria-controls": selector.substring( 1 ), + "aria-labelledby": anchorId + }); + panel.attr( "aria-labelledby", anchorId ); + }); + + this.panels + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .attr( "role", "tabpanel" ); + }, + + // allow overriding how to find the list for rare usage scenarios (#7715) + _getList: function() { + return this.element.find( "ol,ul" ).eq( 0 ); + }, + + _createPanel: function( id ) { + return $( "
      " ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); + }, + + _setupDisabled: function( disabled ) { + if ( $.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; + } + } + + // disable tabs + for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { + if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { + $( li ) + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } else { + $( li ) + .removeClass( "ui-state-disabled" ) + .removeAttr( "aria-disabled" ); + } + } + + this.options.disabled = disabled; + }, + + _setupEvents: function( event ) { + var events = { + click: function( event ) { + event.preventDefault(); + } + }; + if ( event ) { + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); + } + + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + this._on( this.anchors, events ); + this._on( this.tabs, { keydown: "_tabKeydown" } ); + this._on( this.panels, { keydown: "_panelKeydown" } ); + + this._focusable( this.tabs ); + this._hoverable( this.tabs ); + }, + + _setupHeightStyle: function( heightStyle ) { + var maxHeight, overflow, + parent = this.element.parent(); + + if ( heightStyle === "fill" ) { + // IE 6 treats height like minHeight, so we need to turn off overflow + // in order to get a reliable height + // we use the minHeight support test because we assume that only + // browsers that don't support minHeight will treat height as minHeight + if ( !$.support.minHeight ) { + overflow = parent.css( "overflow" ); + parent.css( "overflow", "hidden"); + } + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + }); + if ( overflow ) { + parent.css( "overflow", overflow ); + } + + this.element.children().not( this.panels ).each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.panels.each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.panels.each(function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + }).height( maxHeight ); + } + }, + + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + anchor = $( event.currentTarget ), + tab = anchor.closest( "li" ), + clickedIsActive = tab[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : this._getPanelForTab( tab ), + toHide = !active.length ? $() : this._getPanelForTab( active ), + eventData = { + oldTab: active, + oldPanel: toHide, + newTab: collapsing ? $() : tab, + newPanel: toShow + }; + + event.preventDefault(); + + if ( tab.hasClass( "ui-state-disabled" ) || + // tab is already loading + tab.hasClass( "ui-tabs-loading" ) || + // can't switch durning an animation + this.running || + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.tabs.index( tab ); + + this.active = clickedIsActive ? $() : tab; + if ( this.xhr ) { + this.xhr.abort(); + } + + if ( !toHide.length && !toShow.length ) { + $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); + } + + if ( toShow.length ) { + this.load( this.tabs.index( tab ), event ); + } + this._toggle( event, eventData ); + }, + + // handles show/hide for selecting tabs + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel; + + this.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && that.options.show ) { + that._show( toShow, that.options.show, complete ); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && this.options.hide ) { + this._hide( toHide, this.options.hide, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); + } + + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + eventData.oldTab.attr( "aria-selected", "false" ); + // If we're switching tabs, remove the old tab from the tab order. + // If we're opening from collapsed state, remove the previous tab from the tab order. + // If we're collapsing, then keep the collapsing tab in the tab order. + if ( toShow.length && toHide.length ) { + eventData.oldTab.attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.tabs.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); + } + + toShow.attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + eventData.newTab.attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, + + _activate: function( index ) { + var anchor, + active = this._findActive( index ); + + // trying to activate the already active panel + if ( active[ 0 ] === this.active[ 0 ] ) { + return; + } + + // trying to collapse, simulate a click on the current active header + if ( !active.length ) { + active = this.active; + } + + anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; + this._eventHandler({ + target: anchor, + currentTarget: anchor, + preventDefault: $.noop + }); + }, + + _findActive: function( index ) { + return index === false ? $() : this.tabs.eq( index ); + }, + + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + if ( typeof index === "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); + } + + return index; + }, + + _destroy: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + + this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); + + this.tablist + .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .removeAttr( "role" ); + + this.anchors + .removeClass( "ui-tabs-anchor" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeData( "href.tabs" ) + .removeData( "load.tabs" ) + .removeUniqueId(); + + this.tabs.add( this.panels ).each(function() { + if ( $.data( this, "ui-tabs-destroy" ) ) { + $( this ).remove(); + } else { + $( this ) + .removeClass( "ui-state-default ui-state-active ui-state-disabled " + + "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-live" ) + .removeAttr( "aria-busy" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "role" ); + } + }); + + this.tabs.each(function() { + var li = $( this ), + prev = li.data( "ui-tabs-aria-controls" ); + if ( prev ) { + li.attr( "aria-controls", prev ); + } else { + li.removeAttr( "aria-controls" ); + } + }); + + this.panels.show(); + + if ( this.options.heightStyle !== "content" ) { + this.panels.css( "height", "" ); + } + }, + + enable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === false ) { + return; + } + + if ( index === undefined ) { + disabled = false; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.map( disabled, function( num ) { + return num !== index ? num : null; + }); + } else { + disabled = $.map( this.tabs, function( li, num ) { + return num !== index ? num : null; + }); + } + } + this._setupDisabled( disabled ); + }, + + disable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === true ) { + return; + } + + if ( index === undefined ) { + disabled = true; + } else { + index = this._getIndex( index ); + if ( $.inArray( index, disabled ) !== -1 ) { + return; + } + if ( $.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; + } + } + this._setupDisabled( disabled ); + }, + + load: function( index, event ) { + index = this._getIndex( index ); + var that = this, + tab = this.tabs.eq( index ), + anchor = tab.find( ".ui-tabs-anchor" ), + panel = this._getPanelForTab( tab ), + eventData = { + tab: tab, + panel: panel + }; + + // not remote + if ( isLocal( anchor[ 0 ] ) ) { + return; + } + + this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); + + // support: jQuery <1.8 + // jQuery <1.8 returns false if the request is canceled in beforeSend, + // but as of 1.8, $.ajax() always returns a jqXHR object. + if ( this.xhr && this.xhr.statusText !== "canceled" ) { + tab.addClass( "ui-tabs-loading" ); + panel.attr( "aria-busy", "true" ); + + this.xhr + .success(function( response ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + panel.html( response ); + that._trigger( "load", event, eventData ); + }, 1 ); + }) + .complete(function( jqXHR, status ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + tab.removeClass( "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } + }, 1 ); + }); + } + }, + + // TODO: Remove this function in 1.10 when ajaxOptions is removed + _ajaxSettings: function( anchor, event, eventData ) { + var that = this; + return { + url: anchor.attr( "href" ), + beforeSend: function( jqXHR, settings ) { + return that._trigger( "beforeLoad", event, + $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); + } + }; + }, + + _getPanelForTab: function( tab ) { + var id = $( tab ).attr( "aria-controls" ); + return this.element.find( this._sanitizeSelector( "#" + id ) ); + } +}); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // helper method for a lot of the back compat extensions + $.ui.tabs.prototype._ui = function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }; + + // url method + $.widget( "ui.tabs", $.ui.tabs, { + url: function( index, url ) { + this.anchors.eq( index ).attr( "href", url ); + } + }); + + // TODO: Remove _ajaxSettings() method when removing this extension + // ajaxOptions and cache options + $.widget( "ui.tabs", $.ui.tabs, { + options: { + ajaxOptions: null, + cache: false + }, + + _create: function() { + this._super(); + + var that = this; + + this._on({ tabsbeforeload: function( event, ui ) { + // tab is already cached + if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) { + event.preventDefault(); + return; + } + + ui.jqXHR.success(function() { + if ( that.options.cache ) { + $.data( ui.tab[ 0 ], "cache.tabs", true ); + } + }); + }}); + }, + + _ajaxSettings: function( anchor, event, ui ) { + var ajaxOptions = this.options.ajaxOptions; + return $.extend( {}, ajaxOptions, { + error: function( xhr, status ) { + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + ajaxOptions.error( + xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); + } + catch ( error ) {} + } + }, this._superApply( arguments ) ); + }, + + _setOption: function( key, value ) { + // reset cache if switching from cached to not cached + if ( key === "cache" && value === false ) { + this.anchors.removeData( "cache.tabs" ); + } + this._super( key, value ); + }, + + _destroy: function() { + this.anchors.removeData( "cache.tabs" ); + this._super(); + }, + + url: function( index ){ + this.anchors.eq( index ).removeData( "cache.tabs" ); + this._superApply( arguments ); + } + }); + + // abort method + $.widget( "ui.tabs", $.ui.tabs, { + abort: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + } + }); + + // spinner + $.widget( "ui.tabs", $.ui.tabs, { + options: { + spinner: "Loading…" + }, + _create: function() { + this._super(); + this._on({ + tabsbeforeload: function( event, ui ) { + // Don't react to nested tabs or tabs that don't use a spinner + if ( event.target !== this.element[ 0 ] || + !this.options.spinner ) { + return; + } + + var span = ui.tab.find( "span" ), + html = span.html(); + span.html( this.options.spinner ); + ui.jqXHR.complete(function() { + span.html( html ); + }); + } + }); + } + }); + + // enable/disable events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + enable: null, + disable: null + }, + + enable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === true || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + }, + + disable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === false || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + } + }); + + // add/remove methods and events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + add: null, + remove: null, + tabTemplate: "
    • #{label}
    • " + }, + + add: function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var doInsertAfter, panel, + options = this.options, + li = $( options.tabTemplate + .replace( /#\{href\}/g, url ) + .replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? + url.replace( "#", "" ) : + this._tabId( li ); + + li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true ); + li.attr( "aria-controls", id ); + + doInsertAfter = index >= this.tabs.length; + + // try to find an existing element before creating a new one + panel = this.element.find( "#" + id ); + if ( !panel.length ) { + panel = this._createPanel( id ); + if ( doInsertAfter ) { + if ( index > 0 ) { + panel.insertAfter( this.panels.eq( -1 ) ); + } else { + panel.appendTo( this.element ); + } + } else { + panel.insertBefore( this.panels[ index ] ); + } + } + panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); + + if ( doInsertAfter ) { + li.appendTo( this.tablist ); + } else { + li.insertBefore( this.tabs[ index ] ); + } + + options.disabled = $.map( options.disabled, function( n ) { + return n >= index ? ++n : n; + }); + + this.refresh(); + if ( this.tabs.length === 1 && options.active === false ) { + this.option( "active", 0 ); + } + + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + remove: function( index ) { + index = this._getIndex( index ); + var options = this.options, + tab = this.tabs.eq( index ).remove(), + panel = this._getPanelForTab( tab ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + // We check for more than 2 tabs, because if there are only 2, + // then when we remove this tab, there will only be one tab left + // so we don't need to detect which tab to activate. + if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) { + this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); + } + + options.disabled = $.map( + $.grep( options.disabled, function( n ) { + return n !== index; + }), + function( n ) { + return n >= index ? --n : n; + }); + + this.refresh(); + + this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); + return this; + } + }); + + // length method + $.widget( "ui.tabs", $.ui.tabs, { + length: function() { + return this.anchors.length; + } + }); + + // panel ids (idPrefix option + title attribute) + $.widget( "ui.tabs", $.ui.tabs, { + options: { + idPrefix: "ui-tabs-" + }, + + _tabId: function( tab ) { + var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab; + a = a[0]; + return $( a ).closest( "li" ).attr( "aria-controls" ) || + a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + } + }); + + // _createPanel method + $.widget( "ui.tabs", $.ui.tabs, { + options: { + panelTemplate: "
      " + }, + + _createPanel: function( id ) { + return $( this.options.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); + } + }); + + // selected option + $.widget( "ui.tabs", $.ui.tabs, { + _create: function() { + var options = this.options; + if ( options.active === null && options.selected !== undefined ) { + options.active = options.selected === -1 ? false : options.selected; + } + this._super(); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; + } + }, + + _setOption: function( key, value ) { + if ( key !== "selected" ) { + return this._super( key, value ); + } + + var options = this.options; + this._super( "active", value === -1 ? false : value ); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; + } + }, + + _eventHandler: function() { + this._superApply( arguments ); + this.options.selected = this.options.active; + if ( this.options.selected === false ) { + this.options.selected = -1; + } + } + }); + + // show and select event + $.widget( "ui.tabs", $.ui.tabs, { + options: { + show: null, + select: null + }, + _create: function() { + this._super(); + if ( this.options.active !== false ) { + this._trigger( "show", null, this._ui( + this.active.find( ".ui-tabs-anchor" )[ 0 ], + this._getPanelForTab( this.active )[ 0 ] ) ); + } + }, + _trigger: function( type, event, data ) { + var tab, panel, + ret = this._superApply( arguments ); + + if ( !ret ) { + return false; + } + + if ( type === "beforeActivate" ) { + tab = data.newTab.length ? data.newTab : data.oldTab; + panel = data.newPanel.length ? data.newPanel : data.oldPanel; + ret = this._super( "select", event, { + tab: tab.find( ".ui-tabs-anchor" )[ 0], + panel: panel[ 0 ], + index: tab.closest( "li" ).index() + }); + } else if ( type === "activate" && data.newTab.length ) { + ret = this._super( "show", event, { + tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ], + panel: data.newPanel[ 0 ], + index: data.newTab.closest( "li" ).index() + }); + } + return ret; + } + }); + + // select method + $.widget( "ui.tabs", $.ui.tabs, { + select: function( index ) { + index = this._getIndex( index ); + if ( index === -1 ) { + if ( this.options.collapsible && this.options.selected !== -1 ) { + index = this.options.selected; + } else { + return; + } + } + this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace ); + } + }); + + // cookie option + (function() { + + var listId = 0; + + $.widget( "ui.tabs", $.ui.tabs, { + options: { + cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + }, + _create: function() { + var options = this.options, + active; + if ( options.active == null && options.cookie ) { + active = parseInt( this._cookie(), 10 ); + if ( active === -1 ) { + active = false; + } + options.active = active; + } + this._super(); + }, + _cookie: function( active ) { + var cookie = [ this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ]; + if ( arguments.length ) { + cookie.push( active === false ? -1 : active ); + cookie.push( this.options.cookie ); + } + return $.cookie.apply( null, cookie ); + }, + _refresh: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _eventHandler: function() { + this._superApply( arguments ); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _destroy: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( null, this.options.cookie ); + } + } + }); + + })(); + + // load event + $.widget( "ui.tabs", $.ui.tabs, { + _trigger: function( type, event, data ) { + var _data = $.extend( {}, data ); + if ( type === "load" ) { + _data.panel = _data.panel[ 0 ]; + _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ]; + } + return this._super( type, event, _data ); + } + }); + + // fx option + // The new animation options (show, hide) conflict with the old show callback. + // The old fx option wins over show/hide anyway (always favor back-compat). + // If a user wants to use the new animation API, they must give up the old API. + $.widget( "ui.tabs", $.ui.tabs, { + options: { + fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 } + }, + + _getFx: function() { + var hide, show, + fx = this.options.fx; + + if ( fx ) { + if ( $.isArray( fx ) ) { + hide = fx[ 0 ]; + show = fx[ 1 ]; + } else { + hide = show = fx; + } + } + + return fx ? { show: show, hide: hide } : null; + }, + + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel, + fx = this._getFx(); + + if ( !fx ) { + return this._super( event, eventData ); + } + + that.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && fx.show ) { + toShow + .animate( fx.show, fx.show.duration, function() { + complete(); + }); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && fx.hide ) { + toHide.animate( fx.hide, fx.hide.duration, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); + } + } + }); +} + +})( jQuery ); + +(function( $ ) { + +var increments = 0; + +function addDescribedBy( elem, id ) { + var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); +} + +function removeDescribedBy( elem ) { + var id = elem.data( "ui-tooltip-id" ), + describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), + index = $.inArray( id, describedby ); + if ( index !== -1 ) { + describedby.splice( index, 1 ); + } + + elem.removeData( "ui-tooltip-id" ); + describedby = $.trim( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } +} + +$.widget( "ui.tooltip", { + version: "1.9.2", + options: { + content: function() { + return $( this ).attr( "title" ); + }, + hide: true, + // Disabled elements have inconsistent behavior across browsers (#8661) + items: "[title]:not([disabled])", + position: { + my: "left top+15", + at: "left bottom", + collision: "flipfit flip" + }, + show: true, + tooltipClass: null, + track: false, + + // callbacks + close: null, + open: null + }, + + _create: function() { + this._on({ + mouseover: "open", + focusin: "open" + }); + + // IDs of generated tooltips, needed for destroy + this.tooltips = {}; + // IDs of parent tooltips where we removed the title attribute + this.parents = {}; + + if ( this.options.disabled ) { + this._disable(); + } + }, + + _setOption: function( key, value ) { + var that = this; + + if ( key === "disabled" ) { + this[ value ? "_disable" : "_enable" ](); + this.options[ key ] = value; + // disable element style changes + return; + } + + this._super( key, value ); + + if ( key === "content" ) { + $.each( this.tooltips, function( id, element ) { + that._updateContent( element ); + }); + } + }, + + _disable: function() { + var that = this; + + // close open tooltips + $.each( this.tooltips, function( id, element ) { + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); + }); + + // remove title attributes to prevent native tooltips + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.is( "[title]" ) ) { + element + .data( "ui-tooltip-title", element.attr( "title" ) ) + .attr( "title", "" ); + } + }); + }, + + _enable: function() { + // restore title attributes + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + } + }); + }, + + open: function( event ) { + var that = this, + target = $( event ? event.target : this.element ) + // we need closest here due to mouseover bubbling, + // but always pointing at the same event target + .closest( this.options.items ); + + // No element to show a tooltip for or the tooltip is already open + if ( !target.length || target.data( "ui-tooltip-id" ) ) { + return; + } + + if ( target.attr( "title" ) ) { + target.data( "ui-tooltip-title", target.attr( "title" ) ); + } + + target.data( "ui-tooltip-open", true ); + + // kill parent tooltips, custom or native, for hover + if ( event && event.type === "mouseover" ) { + target.parents().each(function() { + var parent = $( this ), + blurEvent; + if ( parent.data( "ui-tooltip-open" ) ) { + blurEvent = $.Event( "blur" ); + blurEvent.target = blurEvent.currentTarget = this; + that.close( blurEvent, true ); + } + if ( parent.attr( "title" ) ) { + parent.uniqueId(); + that.parents[ this.id ] = { + element: this, + title: parent.attr( "title" ) + }; + parent.attr( "title", "" ); + } + }); + } + + this._updateContent( target, event ); + }, + + _updateContent: function( target, event ) { + var content, + contentOption = this.options.content, + that = this, + eventType = event ? event.type : null; + + if ( typeof contentOption === "string" ) { + return this._open( event, target, contentOption ); + } + + content = contentOption.call( target[0], function( response ) { + // ignore async response if tooltip was closed already + if ( !target.data( "ui-tooltip-open" ) ) { + return; + } + // IE may instantly serve a cached response for ajax requests + // delay this call to _open so the other call to _open runs first + that._delay(function() { + // jQuery creates a special event for focusin when it doesn't + // exist natively. To improve performance, the native event + // object is reused and the type is changed. Therefore, we can't + // rely on the type being correct after the event finished + // bubbling, so we set it back to the previous value. (#8740) + if ( event ) { + event.type = eventType; + } + this._open( event, target, response ); + }); + }); + if ( content ) { + this._open( event, target, content ); + } + }, + + _open: function( event, target, content ) { + var tooltip, events, delayedShow, + positionOption = $.extend( {}, this.options.position ); + + if ( !content ) { + return; + } + + // Content can be updated multiple times. If the tooltip already + // exists, then just update the content and bail. + tooltip = this._find( target ); + if ( tooltip.length ) { + tooltip.find( ".ui-tooltip-content" ).html( content ); + return; + } + + // if we have a title, clear it to prevent the native tooltip + // we have to check first to avoid defining a title if none exists + // (we don't want to cause an element to start matching [title]) + // + // We use removeAttr only for key events, to allow IE to export the correct + // accessible attributes. For mouse events, set to empty string to avoid + // native tooltip showing up (happens only when removing inside mouseover). + if ( target.is( "[title]" ) ) { + if ( event && event.type === "mouseover" ) { + target.attr( "title", "" ); + } else { + target.removeAttr( "title" ); + } + } + + tooltip = this._tooltip( target ); + addDescribedBy( target, tooltip.attr( "id" ) ); + tooltip.find( ".ui-tooltip-content" ).html( content ); + + function position( event ) { + positionOption.of = event; + if ( tooltip.is( ":hidden" ) ) { + return; + } + tooltip.position( positionOption ); + } + if ( this.options.track && event && /^mouse/.test( event.type ) ) { + this._on( this.document, { + mousemove: position + }); + // trigger once to override element-relative positioning + position( event ); + } else { + tooltip.position( $.extend({ + of: target + }, this.options.position ) ); + } + + tooltip.hide(); + + this._show( tooltip, this.options.show ); + // Handle tracking tooltips that are shown with a delay (#8644). As soon + // as the tooltip is visible, position the tooltip using the most recent + // event. + if ( this.options.show && this.options.show.delay ) { + delayedShow = setInterval(function() { + if ( tooltip.is( ":visible" ) ) { + position( positionOption.of ); + clearInterval( delayedShow ); + } + }, $.fx.interval ); + } + + this._trigger( "open", event, { tooltip: tooltip } ); + + events = { + keyup: function( event ) { + if ( event.keyCode === $.ui.keyCode.ESCAPE ) { + var fakeEvent = $.Event(event); + fakeEvent.currentTarget = target[0]; + this.close( fakeEvent, true ); + } + }, + remove: function() { + this._removeTooltip( tooltip ); + } + }; + if ( !event || event.type === "mouseover" ) { + events.mouseleave = "close"; + } + if ( !event || event.type === "focusin" ) { + events.focusout = "close"; + } + this._on( true, target, events ); + }, + + close: function( event ) { + var that = this, + target = $( event ? event.currentTarget : this.element ), + tooltip = this._find( target ); + + // disabling closes the tooltip, so we need to track when we're closing + // to avoid an infinite loop in case the tooltip becomes disabled on close + if ( this.closing ) { + return; + } + + // only set title if we had one before (see comment in _open()) + if ( target.data( "ui-tooltip-title" ) ) { + target.attr( "title", target.data( "ui-tooltip-title" ) ); + } + + removeDescribedBy( target ); + + tooltip.stop( true ); + this._hide( tooltip, this.options.hide, function() { + that._removeTooltip( $( this ) ); + }); + + target.removeData( "ui-tooltip-open" ); + this._off( target, "mouseleave focusout keyup" ); + // Remove 'remove' binding only on delegated targets + if ( target[0] !== this.element[0] ) { + this._off( target, "remove" ); + } + this._off( this.document, "mousemove" ); + + if ( event && event.type === "mouseleave" ) { + $.each( this.parents, function( id, parent ) { + $( parent.element ).attr( "title", parent.title ); + delete that.parents[ id ]; + }); + } + + this.closing = true; + this._trigger( "close", event, { tooltip: tooltip } ); + this.closing = false; + }, + + _tooltip: function( element ) { + var id = "ui-tooltip-" + increments++, + tooltip = $( "
      " ) + .attr({ + id: id, + role: "tooltip" + }) + .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + + ( this.options.tooltipClass || "" ) ); + $( "
      " ) + .addClass( "ui-tooltip-content" ) + .appendTo( tooltip ); + tooltip.appendTo( this.document[0].body ); + if ( $.fn.bgiframe ) { + tooltip.bgiframe(); + } + this.tooltips[ id ] = element; + return tooltip; + }, + + _find: function( target ) { + var id = target.data( "ui-tooltip-id" ); + return id ? $( "#" + id ) : $(); + }, + + _removeTooltip: function( tooltip ) { + tooltip.remove(); + delete this.tooltips[ tooltip.attr( "id" ) ]; + }, + + _destroy: function() { + var that = this; + + // close open tooltips + $.each( this.tooltips, function( id, element ) { + // Delegate to close method to handle common cleanup + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); + + // Remove immediately; destroying an open tooltip doesn't use the + // hide animation + $( "#" + id ).remove(); + + // Restore the title + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + element.removeData( "ui-tooltip-title" ); + } + }); + } +}); + +}( jQuery ) ); diff --git a/js/jquery.basictable.min.js b/js/jquery.basictable.min.js new file mode 100644 index 0000000..64293c9 --- /dev/null +++ b/js/jquery.basictable.min.js @@ -0,0 +1,4 @@ +/* + * jQuery Basic Table + * Author: Jerry Low + */(function(e){e.fn.basictable=function(t){var n=function(t,n){var i=[];n.tableWrap&&t.wrap('
      ');var s="";t.find("thead tr th").length?s="thead th":t.find("tbody tr th").length?s="tbody tr th":t.find("th").length?s="tr:first th":s="tr:first td",e.each(t.find(s),function(){var t=e(this),n=parseInt(t.attr("colspan"),10)||1,r=t.closest("tr").index();i[r]||(i[r]=[]);for(var s=0;s')}else t.addClass("bt-hide")})},i=function(t){e.each(t.find("td"),function(){var t=e(this),n=t.children(".bt-content").html();t.html(n)})},s=function(t,n){n.forceResponsive?e(window).width()<=n.breakpoint?o(t,n):u(t,n):t.removeClass("bt").outerWidth()>t.parent().width()?o(t,n):u(t,n)},o=function(e,t){e.addClass("bt"),t.tableWrap&&e.parent(".bt-wrapper").addClass("active")},u=function(e,t){e.removeClass("bt"),t.tableWrap&&e.parent(".bt-wrapper").removeClass("active")},a=function(e,t){e.find("td").removeAttr("data-th"),t.tableWrap&&e.unwrap(),t.contentWrap&&i(e),e.removeData("basictable")},f=function(e){e.data("basictable")&&s(e,e.data("basictable"))};this.each(function(){var r=e(this);if(r.length===0||r.data("basictable"))return r.data("basictable")&&(t=="destroy"?a(r,r.data("basictable")):t==="start"?o(r,r.data("basictable")):t==="stop"?u(r,r.data("basictable")):s(r,r.data("basictable"))),!1;var i=e.extend({},e.fn.basictable.defaults,t),l={breakpoint:i.breakpoint,contentWrap:i.contentWrap,forceResponsive:i.forceResponsive,noResize:i.noResize,tableWrap:i.tableWrap,showEmptyCells:i.showEmptyCells};r.data("basictable",l),n(r,r.data("basictable")),l.noResize||(s(r,r.data("basictable")),e(window).bind("resize.basictable",function(){f(r)}))})},e.fn.basictable.defaults={breakpoint:568,contentWrap:!0,forceResponsive:!0,noResize:!1,tableWrap:!1,showEmptyCells:!1}})(jQuery); \ No newline at end of file diff --git a/js/jquery.jqcandlestick.min.js b/js/jquery.jqcandlestick.min.js new file mode 100644 index 0000000..eebfa2b --- /dev/null +++ b/js/jquery.jqcandlestick.min.js @@ -0,0 +1,25 @@ +/* +jqCandlestick v0.1.0 + +Copyright (C) 2014 Niels Sonnich Poulsen +http://apakoh.dk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/(function(e){var t=e(window);e.fn.jqCandlestick=function(n){if(n.theme){if(!e.fn.jqCandlestick.themes[n.theme])throw"Undefined theme: "+n.theme;n=e.extend(true,{},e.fn.jqCandlestick.themes[n.theme],n)}var r=e.extend(true,{},e.fn.jqCandlestick.defaults,n);var i=this;i.addClass(r.containerClass);var s=e("").attr(r.chartCanvasAttrs).appendTo(i);var o=e("").attr(r.crossCanvasAttrs).appendTo(i);var u=s.get(0);var a=o.get(0);if(!u.getContext||!a.getContext){throw"canvas unsupported"}var f=r.data;var l=r.xAxis.dataOffset;f.sort(function(e,t){return e[l]-t[l]});if(r.xAxis.min==null||r.xAxis.max==null){var c=null;var h=null;f.forEach(function(e){if(c)c=Math.min(c,e[l]);else c=e[l];if(h)h=Math.max(h,e[l]);else h=e[l]});if(r.xAxis.min==null)r.xAxis.min=c;if(r.xAxis.max==null)r.xAxis.max=h}var p=[];r.yAxis=[].concat(r.yAxis);var d=0;r.yAxis.forEach(function(t){t=e.extend(true,{},r.yAxisDefaults,t);d+=t.height;var n={yAxis:t,height:t.height,min:null,max:null,minY:null,maxY:null,series:[]};if(t.labels.format.fixed!==null){var i=t.labels.format.fixed;n.formatLabel=function(e){if(e!=null)return e.toFixed(i);else return"n/a"}}else if(typeof t.labels.format==="function"){n.formatLabel=t.labels.format}else{n.formatLabel=function(e){return e}}p.push(n)});p.forEach(function(e){e.height=e.height/d});r.series.forEach(function(t){t=e.extend(true,{},r.seriesDefaults,t);var n=p[t.yAxis];if(!n)throw"Undefined y-axis: "+t.yAxis;var i=e.fn.jqCandlestick.types[t.type];if(!i)throw"Unknown plot type: "+t.type;t=e.extend(true,{},i,t);var s=t.dataOffset+i.dataSize;f.forEach(function(e){for(var r=t.dataOffset;r=n.minY&&e<=n.maxY){if(n.min!=null&&n.max!=null){t=n.formatLabel(n.max-(e-n.minY)/(n.maxY-n.minY)*(n.max-n.min))}else{t="n/a"}return true}return false});return t};var y=function(e){return r.xAxis.min+(e-r.xAxis.minX)/(r.xAxis.maxX-r.xAxis.minX)*(r.xAxis.max-r.xAxis.min)};var b=function(e){if(e>=v&&e<=m){var t=y(e);var n=null;var i=null;for(var s=0;s0){e.strokeStyle=r.xAxis.color;e.lineWidth=r.xAxis.strokeWidth;e.beginPath();var s=t-r.xAxis.height-r.padding.bottom-.5;e.moveTo(0,s);e.lineTo(u.width,s);e.stroke();e.font=r.xAxis.labels.font?r.xAxis.labels.font:r.font;e.fillStyle=r.xAxis.labels.color;e.textAlign="center";var o=s+r.xAxis.height/2;var a=r.xAxis.max-r.xAxis.min;var l=Math.ceil((r.xAxis.maxX-r.xAxis.minX)/80);var c=a/l;var h=c/6e4;var d=h/60;var g=d/24;var y=[6e4,2*6e4,5*6e4,10*6e4,15*6e4,30*6e4,60*6e4,2*60*6e4,3*60*6e4,6*60*6e4,12*60*6e4,24*60*6e4];var b=6e4;for(var S=0;Sm)continue;e.fillText(k,N,o);e.beginPath();if(T!=0){e.moveTo(N,s);e.lineTo(N,s-T);e.stroke()}}}e.fillStyle="#900";p.forEach(function(t){t.series.forEach(function(n){n.draw(e,r,t,n,f,w,E)})})};var x=0;var T=0;var N=false;t.mousemove(function(e){N=true;x=e.pageX-i.offset().left+.5;T=e.pageY-i.offset().top+.5});var C=0;var k=0;var L=function(){if(i.width()!=C||i.height()!=k){u.width=i.width();u.height=i.height();a.width=i.width();a.height=i.height();C=i.width();k=i.height();S()}};var A=function(){L();if(!N)return;N=false;var e=a.getContext("2d");e.strokeStyle=r.cross.color;e.lineWidth=r.cross.strokeWidth;e.clearRect(0,0,a.width,a.height);if(x<0||x>=a.width)return;if(T<0||T>=a.height)return;var t=b(x);if(t){x=w(t[r.xAxis.dataOffset])}e.beginPath();e.moveTo(x,0);e.lineTo(x,a.height);e.stroke();e.beginPath();e.moveTo(0,T);e.lineTo(a.width,T);e.stroke();if(t){e.fillStyle=r.info.color;e.font=r.info.font?r.info.font:r.font;if(r.info.position=="right")e.textAlign="right";else e.textAlign="left";if(r.info.position=="auto")e.textBaseline="top";else e.textBaseline="middle";var n=r.padding.top+Math.floor(r.info.height/2)+.5;var i=[];var s=new Date(t[r.xAxis.dataOffset]);i.push(r.xAxis.name+": "+r.info.formatDate(s));p.forEach(function(e){e.series.forEach(function(n){if(n.dataSize==1){i.push(n.name+": "+e.formatLabel(t[n.dataOffset]))}else{for(var r=0;rm){if(r.info.position=="auto")u=x+5;else u=v;o+=r.info.height}e.fillText(t,u,o);if(r.info.wrap=="yes")o+=r.info.height;else u+=n})}}var f=g(T);if(f==null)return;var l=e.measureText(f).width;var c=Math.floor(r.cross.text.height/2);var h=v;var d=h-5;var y=h-10;var E=h-(l+15);if(xh){if(r.downColor)e.fillStyle=r.downColor;else e.fillStyle=r.color;e.fillRect(c-m,h,r.width,v-h);if(r.downStroke){e.strokeStyle=r.downStroke;e.lineWidth=r.downStrokeWidth;e.strokeRect(c-m,h,r.width,v-h)}e.lineTo(c,h);e.moveTo(c,v)}else{if(r.upColor){e.fillStyle=r.upColor;e.fillRect(c-m,v,r.width,h-v)}if(r.upStroke)e.strokeStyle=r.upStroke;else e.strokeStyle=r.color;e.lineWidth=r.upStrokeWidth;e.strokeRect(c-m,v,r.width,h-v);e.lineTo(c,v);e.moveTo(c,h)}e.lineTo(c,d);e.stroke()})}}}})(jQuery) \ No newline at end of file diff --git a/js/jquery.nicescroll.js b/js/jquery.nicescroll.js new file mode 100644 index 0000000..856031d --- /dev/null +++ b/js/jquery.nicescroll.js @@ -0,0 +1,113 @@ +/* jquery.nicescroll 3.5.0 InuYaksa*2013 MIT http://areaaperta.com/nicescroll */(function(e){var z=!1,E=!1,L=5E3,M=2E3,y=0,N=function(){var e=document.getElementsByTagName("script"),e=e[e.length-1].src.split("?")[0];return 0e){if(b.getScrollTop()>=b.page.maxh)return!0}else if(0>=b.getScrollTop())return!0; + b.scrollmom&&b.scrollmom.stop();b.lastdeltay+=e;b.debounced("mousewheely",function(){var d=b.lastdeltay;b.lastdeltay=0;b.rail.drag||b.doScrollBy(d)},120)}d.stopImmediatePropagation();return d.preventDefault()}var b=this;this.version="3.5.0";this.name="nicescroll";this.me=c;this.opt={doc:e("body"),win:!1};e.extend(this.opt,I);this.opt.snapbackspeed=80;if(h)for(var p in b.opt)"undefined"!=typeof h[p]&&(b.opt[p]=h[p]);this.iddoc=(this.doc=b.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/BODY|HTML/.test(b.opt.win? + b.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper=!1!==b.opt.win;this.win=b.opt.win||(this.ispage?e(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?e(window):this.win;this.body=e("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=b.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin= + this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick=this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.observerremover=this.observer=this.scrollmom=this.scrollrunning=this.checkrtlmode=!1;do this.id="ascrail"+M++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed= + this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=!1;this.cursoractive=!0;this.overflowx=b.opt.overflowx;this.overflowy=b.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=P();var g=e.extend({},this.detected);this.ishwscroll=(this.canhwscroll=g.hastransform&&b.opt.hwacceleration)&&b.haswrapper;this.istouchcapable=!1;g.cantouch&&(g.ischrome&&!g.isios&&!g.isandroid)&& +(this.istouchcapable=!0,g.cantouch=!1);g.cantouch&&(g.ismozilla&&!g.isios&&!g.isandroid)&&(this.istouchcapable=!0,g.cantouch=!1);b.opt.enablemouselockapi||(g.hasmousecapture=!1,g.haspointerlock=!1);this.delayed=function(d,c,f,g){var e=b.delaylist[d],k=(new Date).getTime();if(!g&&e&&e.tt)return!1;e&&e.tt&&clearTimeout(e.tt);if(e&&e.last+f>k&&!e.tt)b.delaylist[d]={last:k+f,tt:setTimeout(function(){b.delaylist[d].tt=0;c.call()},f)};else if(!e||!e.tt)b.delaylist[d]={last:k,tt:0},setTimeout(function(){c.call()}, + 0)};this.debounced=function(d,c,f){var g=b.delaylist[d];(new Date).getTime();b.delaylist[d]=c;g||setTimeout(function(){var c=b.delaylist[d];b.delaylist[d]=!1;c.call()},f)};this.synched=function(d,c){b.synclist[d]=c;(function(){b.onsync||(v(function(){b.onsync=!1;for(d in b.synclist){var c=b.synclist[d];c&&c.call(b);b.synclist[d]=!1}}),b.onsync=!0)})();return d};this.unsynched=function(d){b.synclist[d]&&(b.synclist[d]=!1)};this.css=function(d,c){for(var f in c)b.saved.css.push([d,f,d.css(f)]),d.css(f, + c[f])};this.scrollTop=function(d){return"undefined"==typeof d?b.getScrollTop():b.setScrollTop(d)};this.scrollLeft=function(d){return"undefined"==typeof d?b.getScrollLeft():b.setScrollLeft(d)};BezierClass=function(b,c,f,g,e,k,l){this.st=b;this.ed=c;this.spd=f;this.p1=g||0;this.p2=e||1;this.p3=k||0;this.p4=l||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};BezierClass.prototype={B2:function(b){return 3*b*b*(1-b)},B3:function(b){return 3*b*(1-b)*(1-b)},B4:function(b){return(1-b)*(1-b)*(1-b)}, + getNow:function(){var b=1-((new Date).getTime()-this.ts)/this.spd,c=this.B2(b)+this.B3(b)+this.B4(b);return 0>b?this.ed:this.st+Math.round(this.df*c)},update:function(b,c){this.st=this.getNow();this.ed=b;this.spd=c;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};g.hastranslate3d&&g.isios&&this.doc.css("-webkit-backface-visibility","hidden");var s=function(){var d=b.doc.css(g.trstyle);return d&&"matrix"==d.substr(0, + 6)?d.replace(/^.*\((.*)\)$/g,"$1").replace(/px/g,"").split(/, +/):!1};this.getScrollTop=function(d){if(!d){if(d=s())return 16==d.length?-d[13]:-d[5];if(b.timerscroll&&b.timerscroll.bz)return b.timerscroll.bz.getNow()}return b.doc.translate.y};this.getScrollLeft=function(d){if(!d){if(d=s())return 16==d.length?-d[12]:-d[4];if(b.timerscroll&&b.timerscroll.bh)return b.timerscroll.bh.getNow()}return b.doc.translate.x};this.notifyScrollEvent=document.createEvent?function(b){var c=document.createEvent("UIEvents"); + c.initUIEvent("scroll",!1,!0,window,1);b.dispatchEvent(c)}:document.fireEvent?function(b){var c=document.createEventObject();b.fireEvent("onscroll");c.cancelBubble=!0}:function(b,c){};g.hastranslate3d&&b.opt.enabletranslate3d?(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+"px";b.doc.css(g.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1* + d+"px";b.doc.css(g.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");c||b.notifyScrollEvent(b.win[0])}):(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+"px";b.doc.css(g.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1*d+"px";b.doc.css(g.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");c||b.notifyScrollEvent(b.win[0])})}else this.getScrollTop= + function(){return b.docscroll.scrollTop()},this.setScrollTop=function(d){return b.docscroll.scrollTop(d)},this.getScrollLeft=function(){return b.docscroll.scrollLeft()},this.setScrollLeft=function(d){return b.docscroll.scrollLeft(d)};this.getTarget=function(b){return!b?!1:b.target?b.target:b.srcElement?b.srcElement:!1};this.hasParent=function(b,c){if(!b)return!1;for(var f=b.target||b.srcElement||b||!1;f&&f.id!=c;)f=f.parentNode||!1;return!1!==f};var u={thin:1,medium:3,thick:5};this.getOffset=function(){if(b.isfixed)return{top:parseFloat(b.win.css("top")), + left:parseFloat(b.win.css("left"))};if(!b.viewport)return b.win.offset();var d=b.win.offset(),c=b.viewport.offset();return{top:d.top-c.top+b.viewport.scrollTop(),left:d.left-c.left+b.viewport.scrollLeft()}};this.updateScrollBar=function(d){if(b.ishwscroll)b.rail.css({height:b.win.innerHeight()}),b.railh&&b.railh.css({width:b.win.innerWidth()});else{var c=b.getOffset(),f=c.top,g=c.left,f=f+l(b.win,"border-top-width",!0);b.win.outerWidth();b.win.innerWidth();var g=g+(b.rail.align?b.win.outerWidth()- + l(b.win,"border-right-width")-b.rail.width:l(b.win,"border-left-width")),e=b.opt.railoffset;e&&(e.top&&(f+=e.top),b.rail.align&&e.left&&(g+=e.left));b.locked||b.rail.css({top:f,left:g,height:d?d.h:b.win.innerHeight()});b.zoom&&b.zoom.css({top:f+1,left:1==b.rail.align?g-20:g+b.rail.width+4});b.railh&&!b.locked&&(f=c.top,g=c.left,d=b.railh.align?f+l(b.win,"border-top-width",!0)+b.win.innerHeight()-b.railh.height:f+l(b.win,"border-top-width",!0),g+=l(b.win,"border-left-width"),b.railh.css({top:d,left:g, + width:b.railh.width}))}};this.doRailClick=function(d,c,f){var g;b.locked||(b.cancelEvent(d),c?(c=f?b.doScrollLeft:b.doScrollTop,g=f?(d.pageX-b.railh.offset().left-b.cursorwidth/2)*b.scrollratio.x:(d.pageY-b.rail.offset().top-b.cursorheight/2)*b.scrollratio.y,c(g)):(c=f?b.doScrollLeftBy:b.doScrollBy,g=f?b.scroll.x:b.scroll.y,d=f?d.pageX-b.railh.offset().left:d.pageY-b.rail.offset().top,f=f?b.view.w:b.view.h,g>=d?c(f):c(-f)))};b.hasanimationframe=v;b.hascancelanimationframe=w;b.hasanimationframe?b.hascancelanimationframe|| + (w=function(){b.cancelAnimationFrame=!0}):(v=function(b){return setTimeout(b,15-Math.floor(+new Date/1E3)%16)},w=clearInterval);this.init=function(){b.saved.css=[];if(g.isie7mobile||g.isoperamini)return!0;g.hasmstouch&&b.css(b.ispage?e("html"):b.win,{"-ms-touch-action":"none"});b.zindex="auto";b.zindex=!b.ispage&&"auto"==b.opt.zindex?k()||"auto":b.opt.zindex;!b.ispage&&"auto"!=b.zindex&&b.zindex>y&&(y=b.zindex);b.isie&&(0==b.zindex&&"auto"==b.opt.zindex)&&(b.zindex="auto");if(!b.ispage||!g.cantouch&& + !g.isieold&&!g.isie9mobile){var d=b.docscroll;b.ispage&&(d=b.haswrapper?b.win:b.doc);g.isie9mobile||b.css(d,{"overflow-y":"hidden"});b.ispage&&g.isie7&&("BODY"==b.doc[0].nodeName?b.css(e("html"),{"overflow-y":"hidden"}):"HTML"==b.doc[0].nodeName&&b.css(e("body"),{"overflow-y":"hidden"}));g.isios&&(!b.ispage&&!b.haswrapper)&&b.css(e("body"),{"-webkit-overflow-scrolling":"touch"});var c=e(document.createElement("div"));c.css({position:"relative",top:0,"float":"right",width:b.opt.cursorwidth,height:"0px", + "background-color":b.opt.cursorcolor,border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius,"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});c.hborder=parseFloat(c.outerHeight()-c.innerHeight());b.cursor=c;var f=e(document.createElement("div"));f.attr("id",b.id);f.addClass("nicescroll-rails");var l,h,x=["left","right"],q;for(q in x)h=x[q],(l=b.opt.railpadding[h])?f.css("padding-"+h,l+"px"):b.opt.railpadding[h]= + 0;f.append(c);f.width=Math.max(parseFloat(b.opt.cursorwidth),c.outerWidth())+b.opt.railpadding.left+b.opt.railpadding.right;f.css({width:f.width+"px",zIndex:b.zindex,background:b.opt.background,cursor:"default"});f.visibility=!0;f.scrollable=!0;f.align="left"==b.opt.railalign?0:1;b.rail=f;c=b.rail.drag=!1;b.opt.boxzoom&&(!b.ispage&&!g.isieold)&&(c=document.createElement("div"),b.bind(c,"click",b.doZoom),b.zoom=e(c),b.zoom.css({cursor:"pointer","z-index":b.zindex,backgroundImage:"url("+N+"zoomico.png)", + height:18,width:18,backgroundPosition:"0px 0px"}),b.opt.dblclickzoom&&b.bind(b.win,"dblclick",b.doZoom),g.cantouch&&b.opt.gesturezoom&&(b.ongesturezoom=function(d){1.5d.scale&&b.doZoomOut(d);return b.cancelEvent(d)},b.bind(b.win,"gestureend",b.ongesturezoom)));b.railh=!1;if(b.opt.horizrailenabled){b.css(d,{"overflow-x":"hidden"});c=e(document.createElement("div"));c.css({position:"relative",top:0,height:b.opt.cursorwidth,width:"0px","background-color":b.opt.cursorcolor, + border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius,"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});c.wborder=parseFloat(c.outerWidth()-c.innerWidth());b.cursorh=c;var m=e(document.createElement("div"));m.attr("id",b.id+"-hr");m.addClass("nicescroll-rails");m.height=Math.max(parseFloat(b.opt.cursorwidth),c.outerHeight());m.css({height:m.height+"px",zIndex:b.zindex,background:b.opt.background});m.append(c); + m.visibility=!0;m.scrollable=!0;m.align="top"==b.opt.railvalign?0:1;b.railh=m;b.railh.drag=!1}b.ispage?(f.css({position:"fixed",top:"0px",height:"100%"}),f.align?f.css({right:"0px"}):f.css({left:"0px"}),b.body.append(f),b.railh&&(m.css({position:"fixed",left:"0px",width:"100%"}),m.align?m.css({bottom:"0px"}):m.css({top:"0px"}),b.body.append(m))):(b.ishwscroll?("static"==b.win.css("position")&&b.css(b.win,{position:"relative"}),d="HTML"==b.win[0].nodeName?b.body:b.win,b.zoom&&(b.zoom.css({position:"absolute", + top:1,right:0,"margin-right":f.width+4}),d.append(b.zoom)),f.css({position:"absolute",top:0}),f.align?f.css({right:0}):f.css({left:0}),d.append(f),m&&(m.css({position:"absolute",left:0,bottom:0}),m.align?m.css({bottom:0}):m.css({top:0}),d.append(m))):(b.isfixed="fixed"==b.win.css("position"),d=b.isfixed?"fixed":"absolute",b.isfixed||(b.viewport=b.getViewport(b.win[0])),b.viewport&&(b.body=b.viewport,!1==/fixed|relative|absolute/.test(b.viewport.css("position"))&&b.css(b.viewport,{position:"relative"})), + f.css({position:d}),b.zoom&&b.zoom.css({position:d}),b.updateScrollBar(),b.body.append(f),b.zoom&&b.body.append(b.zoom),b.railh&&(m.css({position:d}),b.body.append(m))),g.isios&&b.css(b.win,{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),g.isie&&b.opt.disableoutline&&b.win.attr("hideFocus","true"),g.iswebkit&&b.opt.disableoutline&&b.win.css({outline:"none"}));!1===b.opt.autohidemode?(b.autohidedom=!1,b.rail.css({opacity:b.opt.cursoropacitymax}),b.railh&&b.railh.css({opacity:b.opt.cursoropacitymax})): + !0===b.opt.autohidemode||"leave"===b.opt.autohidemode?(b.autohidedom=e().add(b.rail),g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursor)),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh)),b.railh&&g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"scroll"==b.opt.autohidemode?(b.autohidedom=e().add(b.rail),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh))):"cursor"==b.opt.autohidemode?(b.autohidedom=e().add(b.cursor),b.railh&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"hidden"==b.opt.autohidemode&& + (b.autohidedom=!1,b.hide(),b.locked=!1);if(g.isie9mobile)b.scrollmom=new J(b),b.onmangotouch=function(d){d=b.getScrollTop();var c=b.getScrollLeft();if(d==b.scrollmom.lastscrolly&&c==b.scrollmom.lastscrollx)return!0;var f=d-b.mangotouch.sy,g=c-b.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(g,2)+Math.pow(f,2)))){var n=0>f?-1:1,e=0>g?-1:1,k=+new Date;b.mangotouch.lazy&&clearTimeout(b.mangotouch.lazy);80r?r=Math.round(r/2):r>b.page.maxh&&(r=b.page.maxh+Math.round((r-b.page.maxh)/ + 2)):(0>r&&(k=r=0),r>b.page.maxh&&(r=b.page.maxh,k=0));if(b.railh&&b.railh.scrollable){var m=b.rail.drag.sl-h;b.ishwscroll&&b.opt.bouncescroll?0>m?m=Math.round(m/2):m>b.page.maxw&&(m=b.page.maxw+Math.round((m-b.page.maxw)/2)):(0>m&&(l=m=0),m>b.page.maxw&&(m=b.page.maxw,l=0))}f=!1;if(b.rail.drag.dl)f=!0,"v"==b.rail.drag.dl?m=b.rail.drag.sl:"h"==b.rail.drag.dl&&(r=b.rail.drag.st);else{var n=Math.abs(n),h=Math.abs(h),x=b.opt.directionlockdeadzone;if("v"==b.rail.drag.ck){if(n>x&&h<=0.3*n)return b.rail.drag= + !1,!0;h>x&&(b.rail.drag.dl="f",e("body").scrollTop(e("body").scrollTop()))}else if("h"==b.rail.drag.ck){if(h>x&&n<=0.3*h)return b.rail.drag=!1,!0;n>x&&(b.rail.drag.dl="f",e("body").scrollLeft(e("body").scrollLeft()))}}b.synched("touchmove",function(){b.rail.drag&&2==b.rail.drag.pt&&(b.prepareTransition&&b.prepareTransition(0),b.rail.scrollable&&b.setScrollTop(r),b.scrollmom.update(l,k),b.railh&&b.railh.scrollable?(b.setScrollLeft(m),b.showCursor(r,m)):b.showCursor(r),g.isie10&&document.selection.clear())}); + g.ischrome&&b.istouchcapable&&(f=!1);if(f)return b.cancelEvent(d)}}}b.onmousedown=function(d,c){if(!(b.rail.drag&&1!=b.rail.drag.pt)){if(b.locked)return b.cancelEvent(d);b.cancelScroll();b.rail.drag={x:d.clientX,y:d.clientY,sx:b.scroll.x,sy:b.scroll.y,pt:1,hr:!!c};var f=b.getTarget(d);!b.ispage&&g.hasmousecapture&&f.setCapture();b.isiframe&&!g.hasmousecapture&&(b.saved.csspointerevents=b.doc.css("pointer-events"),b.css(b.doc,{"pointer-events":"none"}));return b.cancelEvent(d)}};b.onmouseup=function(d){if(b.rail.drag&& + (g.hasmousecapture&&document.releaseCapture(),b.isiframe&&!g.hasmousecapture&&b.doc.css("pointer-events",b.saved.csspointerevents),1==b.rail.drag.pt))return b.rail.drag=!1,b.cancelEvent(d)};b.onmousemove=function(d){if(b.rail.drag&&1==b.rail.drag.pt){if(g.ischrome&&0==d.which)return b.onmouseup(d);b.cursorfreezed=!0;if(b.rail.drag.hr){b.scroll.x=b.rail.drag.sx+(d.clientX-b.rail.drag.x);0>b.scroll.x&&(b.scroll.x=0);var c=b.scrollvaluemaxw;b.scroll.x>c&&(b.scroll.x=c)}else b.scroll.y=b.rail.drag.sy+ + (d.clientY-b.rail.drag.y),0>b.scroll.y&&(b.scroll.y=0),c=b.scrollvaluemax,b.scroll.y>c&&(b.scroll.y=c);b.synched("mousemove",function(){b.rail.drag&&1==b.rail.drag.pt&&(b.showCursor(),b.rail.drag.hr?b.doScrollLeft(Math.round(b.scroll.x*b.scrollratio.x),b.opt.cursordragspeed):b.doScrollTop(Math.round(b.scroll.y*b.scrollratio.y),b.opt.cursordragspeed))});return b.cancelEvent(d)}};if(g.cantouch||b.opt.touchbehavior)b.onpreventclick=function(d){if(b.preventclick)return b.preventclick.tg.onclick=b.preventclick.click, + b.preventclick=!1,b.cancelEvent(d)},b.bind(b.win,"mousedown",b.ontouchstart),b.onclick=g.isios?!1:function(d){return b.lastmouseup?(b.lastmouseup=!1,b.cancelEvent(d)):!0},b.opt.grabcursorenabled&&g.cursorgrabvalue&&(b.css(b.ispage?b.doc:b.win,{cursor:g.cursorgrabvalue}),b.css(b.rail,{cursor:g.cursorgrabvalue}));else{var p=function(d){if(b.selectiondrag){if(d){var c=b.win.outerHeight();d=d.pageY-b.selectiondrag.top;0=c&&(d-=c);b.selectiondrag.df=d}0!=b.selectiondrag.df&&(b.doScrollBy(2* + -Math.floor(b.selectiondrag.df/6)),b.debounced("doselectionscroll",function(){p()},50))}};b.hasTextSelected="getSelection"in document?function(){return 0b.page.maxh?b.doScrollTop(b.page.maxh):(b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y)),b.scroll.x=Math.round(b.getScrollLeft()* + (1/b.scrollratio.x)),b.cursoractive&&b.noticeCursor());b.scroll.y&&0==b.getScrollTop()&&b.doScrollTo(Math.floor(b.scroll.y*b.scrollratio.y));return b};this.resize=b.onResize;this.lazyResize=function(d){d=isNaN(d)?30:d;b.delayed("resize",b.resize,d);return b};this._bind=function(d,c,f,g){b.events.push({e:d,n:c,f:f,b:g,q:!1});d.addEventListener?d.addEventListener(c,f,g||!1):d.attachEvent?d.attachEvent("on"+c,f):d["on"+c]=f};this.jqbind=function(d,c,f){b.events.push({e:d,n:c,f:f,q:!0});e(d).bind(c,f)}; + this.bind=function(d,c,f,e){var k="jquery"in d?d[0]:d;"mousewheel"==c?"onwheel"in b.win?b._bind(k,"wheel",f,e||!1):(d="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",q(k,d,f,e||!1),"DOMMouseScroll"==d&&q(k,"MozMousePixelScroll",f,e||!1)):k.addEventListener?(g.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&b._bind(k,"mousedown"==c?"touchstart":"mouseup"==c?"touchend":"touchmove",function(b){if(b.touches){if(2>b.touches.length){var d=b.touches.length?b.touches[0]:b;d.original= + b;f.call(this,d)}}else b.changedTouches&&(d=b.changedTouches[0],d.original=b,f.call(this,d))},e||!1),b._bind(k,c,f,e||!1),g.cantouch&&"mouseup"==c&&b._bind(k,"touchcancel",f,e||!1)):b._bind(k,c,function(d){if((d=d||window.event||!1)&&d.srcElement)d.target=d.srcElement;"pageY"in d||(d.pageX=d.clientX+document.documentElement.scrollLeft,d.pageY=d.clientY+document.documentElement.scrollTop);return!1===f.call(k,d)||!1===e?b.cancelEvent(d):!0})};this._unbind=function(b,c,f,g){b.removeEventListener?b.removeEventListener(c, + f,g):b.detachEvent?b.detachEvent("on"+c,f):b["on"+c]=!1};this.unbindAll=function(){for(var d=0;d(b.newscrolly-k)*(e-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();!1==b.opt.bouncescroll&&(0>e?e=0:e>b.page.maxh&&(e=b.page.maxh),0>c?c=0:c>b.page.maxw&&(c=b.page.maxw)); + if(b.scrollrunning&&c==b.newscrollx&&e==b.newscrolly)return!1;b.newscrolly=e;b.newscrollx=c;b.newscrollspeed=f||!1;if(b.timer)return!1;b.timer=setTimeout(function(){var f=b.getScrollTop(),k=b.getScrollLeft(),l,h;l=c-k;h=e-f;l=Math.round(Math.sqrt(Math.pow(l,2)+Math.pow(h,2)));l=b.newscrollspeed&&1=b.newscrollspeed&&(l*=b.newscrollspeed);b.prepareTransition(l,!0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm); + 0c?c=0:c>b.page.maxh&&(c=b.page.maxh);0>e?e=0:e>b.page.maxw&&(e=b.page.maxw);if(c!=b.newscrolly||e!=b.newscrollx)return b.doScrollPos(e,c,b.opt.snapbackspeed);b.onscrollend&&b.scrollrunning&&b.onscrollend.call(b,{type:"scrollend",current:{x:e,y:c},end:{x:b.newscrollx,y:b.newscrolly}});b.scrollrunning=!1}):(this.doScrollLeft=function(c,g){var f=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c, + g){var f=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(f,c,g)},this.doScrollPos=function(c,g,f){function e(){if(b.cancelAnimationFrame)return!0;b.scrollrunning=!0;if(p=1-p)return b.timer=v(e)||1;var c=0,d=sy=b.getScrollTop();if(b.dst.ay){var d=b.bzscroll?b.dst.py+b.bzscroll.getNow()*b.dst.ay:b.newscrolly,f=d-sy;if(0>f&&db.newscrolly)d=b.newscrolly;b.setScrollTop(d);d==b.newscrolly&&(c=1)}else c=1;var g=sx=b.getScrollLeft();if(b.dst.ax){g=b.bzscroll?b.dst.px+b.bzscroll.getNow()* + b.dst.ax:b.newscrollx;f=g-sx;if(0>f&&gb.newscrollx)g=b.newscrollx;b.setScrollLeft(g);g==b.newscrollx&&(c+=1)}else c+=1;2==c?(b.timer=0,b.cursorfreezed=!1,b.bzscroll=!1,b.scrollrunning=!1,0>d?d=0:d>b.page.maxh&&(d=b.page.maxh),0>g?g=0:g>b.page.maxw&&(g=b.page.maxw),g!=b.newscrollx||d!=b.newscrolly?b.doScrollPos(g,d):b.onscrollend&&b.onscrollend.call(b,{type:"scrollend",current:{x:sx,y:sy},end:{x:b.newscrollx,y:b.newscrolly}})):b.timer=v(e)||1}g="undefined"==typeof g||!1===g?b.getScrollTop(!0): + g;if(b.timer&&b.newscrolly==g&&b.newscrollx==c)return!0;b.timer&&w(b.timer);b.timer=0;var k=b.getScrollTop(),l=b.getScrollLeft();(0>(b.newscrolly-k)*(g-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();b.newscrolly=g;b.newscrollx=c;if(!b.bouncescroll||!b.rail.visibility)0>b.newscrolly?b.newscrolly=0:b.newscrolly>b.page.maxh&&(b.newscrolly=b.page.maxh);if(!b.bouncescroll||!b.railh.visibility)0>b.newscrollx?b.newscrollx=0:b.newscrollx>b.page.maxw&&(b.newscrollx=b.page.maxw);b.dst={};b.dst.x=c-l;b.dst.y= + g-k;b.dst.px=l;b.dst.py=k;var h=Math.round(Math.sqrt(Math.pow(b.dst.x,2)+Math.pow(b.dst.y,2)));b.dst.ax=b.dst.x/h;b.dst.ay=b.dst.y/h;var m=0,q=h;0==b.dst.x?(m=k,q=g,b.dst.ay=1,b.dst.py=0):0==b.dst.y&&(m=l,q=c,b.dst.ax=1,b.dst.px=0);h=b.getTransitionSpeed(h);f&&1>=f&&(h*=f);b.bzscroll=0=b.page.maxh||l==b.page.maxw&&c>=b.page.maxw)&&b.checkContentSize();var p=1;b.cancelAnimationFrame=!1;b.timer=1; + b.onscrollstart&&!b.scrollrunning&&b.onscrollstart.call(b,{type:"scrollstart",current:{x:l,y:k},request:{x:c,y:g},end:{x:b.newscrollx,y:b.newscrolly},speed:h});e();(k==b.page.maxh&&g>=k||l==b.page.maxw&&c>=l)&&b.checkContentSize();b.noticeCursor()}},this.cancelScroll=function(){b.timer&&w(b.timer);b.timer=0;b.bzscroll=!1;b.scrollrunning=!1;return b}):(this.doScrollLeft=function(c,g){var f=b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,g){var f=b.getScrollLeft();b.doScrollPos(f, + c,g)},this.doScrollPos=function(c,g,f){var e=c>b.page.maxw?b.page.maxw:c;0>e&&(e=0);var k=g>b.page.maxh?b.page.maxh:g;0>k&&(k=0);b.synched("scroll",function(){b.setScrollTop(k);b.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.y-c)*b.scrollratio.y):(b.timer?b.newscrolly:b.getScrollTop(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.h/2);f<-e?f=-e:f>b.page.maxh+e&&(f=b.page.maxh+e)}b.cursorfreezed=!1;py=b.getScrollTop(!0);if(0>f&& + 0>=py)return b.noticeCursor();if(f>b.page.maxh&&py>=b.page.maxh)return b.checkContentSize(),b.noticeCursor();b.doScrollTop(f)};this.doScrollLeftBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.x-c)*b.scrollratio.x):(b.timer?b.newscrollx:b.getScrollLeft(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.w/2);f<-e?f=-e:f>b.page.maxw+e&&(f=b.page.maxw+e)}b.cursorfreezed=!1;px=b.getScrollLeft(!0);if(0>f&&0>=px||f>b.page.maxw&&px>=b.page.maxw)return b.noticeCursor();b.doScrollLeft(f)};this.doScrollTo= + function(c,g){g&&Math.round(c*b.scrollratio.y);b.cursorfreezed=!1;b.doScrollTop(c)};this.checkContentSize=function(){var c=b.getContentSize();(c.h!=b.page.h||c.w!=b.page.w)&&b.resize(!1,c)};b.onscroll=function(c){b.rail.drag||b.cursorfreezed||b.synched("scroll",function(){b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.railh&&(b.scroll.x=Math.round(b.getScrollLeft()*(1/b.scrollratio.x)));b.noticeCursor()})};b.bind(b.docscroll,"scroll",b.onscroll);this.doZoomIn=function(c){if(!b.zoomactive){b.zoomactive= + !0;b.zoomrestore={style:{}};var k="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),f=b.win[0].style,l;for(l in k){var h=k[l];b.zoomrestore.style[h]="undefined"!=typeof f[h]?f[h]:""}b.zoomrestore.style.width=b.win.css("width");b.zoomrestore.style.height=b.win.css("height");b.zoomrestore.padding={w:b.win.outerWidth()-b.win.width(),h:b.win.outerHeight()-b.win.height()};g.isios4&&(b.zoomrestore.scrollTop=e(window).scrollTop(),e(window).scrollTop(0)); + b.win.css({position:g.isios4?"absolute":"fixed",top:0,left:0,"z-index":y+100,margin:"0px"});k=b.win.css("backgroundColor");(""==k||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(k))&&b.win.css("backgroundColor","#fff");b.rail.css({"z-index":y+101});b.zoom.css({"z-index":y+102});b.zoom.css("backgroundPosition","0px -18px");b.resizeZoom();b.onzoomin&&b.onzoomin.call(b);return b.cancelEvent(c)}};this.doZoomOut=function(c){if(b.zoomactive)return b.zoomactive=!1,b.win.css("margin",""),b.win.css(b.zoomrestore.style), + g.isios4&&e(window).scrollTop(b.zoomrestore.scrollTop),b.rail.css({"z-index":b.zindex}),b.zoom.css({"z-index":b.zindex}),b.zoomrestore=!1,b.zoom.css("backgroundPosition","0px 0px"),b.onResize(),b.onzoomout&&b.onzoomout.call(b),b.cancelEvent(c)};this.doZoom=function(c){return b.zoomactive?b.doZoomOut(c):b.doZoomIn(c)};this.resizeZoom=function(){if(b.zoomactive){var c=b.getScrollTop();b.win.css({width:e(window).width()-b.zoomrestore.padding.w+"px",height:e(window).height()-b.zoomrestore.padding.h+"px"}); + b.onResize();b.setScrollTop(Math.min(b.page.maxh,c))}};this.init();e.nicescroll.push(this)},J=function(e){var c=this;this.nc=e;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(e,l){c.stop();var h=c.time();c.steptime=0;c.lasttime=h;c.speedx=0;c.speedy=0;c.lastx=e;c.lasty=l;c.lastscrollx=-1;c.lastscrolly= + -1};this.update=function(e,l){var h=c.time();c.steptime=h-c.lasttime;c.lasttime=h;var h=l-c.lasty,t=e-c.lastx,b=c.nc.getScrollTop(),p=c.nc.getScrollLeft(),b=b+h,p=p+t;c.snapx=0>p||p>c.nc.page.maxw;c.snapy=0>b||b>c.nc.page.maxh;c.speedx=t;c.speedy=h;c.lastx=e;c.lasty=l};this.stop=function(){c.nc.unsynched("domomentum2d");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(e,l){var h=!1;0>l?(l=0,h=!0):l>c.nc.page.maxh&&(l=c.nc.page.maxh,h=!0);0>e?(e=0,h= + !0):e>c.nc.page.maxw&&(e=c.nc.page.maxw,h=!0);h&&c.nc.doScrollPos(e,l,c.nc.opt.snapbackspeed)};this.doMomentum=function(e){var l=c.time(),h=e?l+e:c.lasttime;e=c.nc.getScrollLeft();var t=c.nc.getScrollTop(),b=c.nc.page.maxh,p=c.nc.page.maxw;c.speedx=0=l-h;if(0>t||t>b||0>e||e>p)h=!1;e=c.speedx&&h?c.speedx:!1;if(c.speedy&&h&&c.speedy||e){var g=Math.max(16,c.steptime);50s||s>p))e=0.1;if(c.speedy&&(u=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=u,0>u||u>b))e=0.1;c.demulxy=Math.min(1,c.demulxy+e);c.nc.synched("domomentum2d",function(){c.speedx&&(c.nc.getScrollLeft()!=c.chkx&&c.stop(),c.chkx= + s,c.nc.setScrollLeft(s));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=u,c.nc.setScrollTop(u));c.timer||(c.nc.hideCursor(),c.doSnapy(s,u))});1>c.demulxy?c.timer=setTimeout(d,g):(c.stop(),c.nc.hideCursor(),c.doSnapy(s,u))};d()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},B=e.fn.scrollTop;e.cssHooks.pageYOffset={get:function(h,c,k){return(c=e.data(h,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollTop():B.call(h)},set:function(h,c){var k=e.data(h,"__nicescroll")||!1;k&&k.ishwscroll? + k.setScrollTop(parseInt(c)):B.call(h,c);return this}};e.fn.scrollTop=function(h){if("undefined"==typeof h){var c=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():B.call(this)}return this.each(function(){var c=e.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(h)):B.call(e(this),h)})};var C=e.fn.scrollLeft;e.cssHooks.pageXOffset={get:function(h,c,k){return(c=e.data(h,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollLeft():C.call(h)},set:function(h, + c){var k=e.data(h,"__nicescroll")||!1;k&&k.ishwscroll?k.setScrollLeft(parseInt(c)):C.call(h,c);return this}};e.fn.scrollLeft=function(h){if("undefined"==typeof h){var c=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():C.call(this)}return this.each(function(){var c=e.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(h)):C.call(e(this),h)})};var D=function(h){var c=this;this.length=0;this.name="nicescrollarray";this.each=function(e){for(var h= + 0,k=0;h0&&b-1 in a}function d(a,b,c){if(_.isFunction(b))return _.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return _.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(ha.test(b))return _.filter(b,a,c);b=_.filter(b,a)}return _.grep(a,function(a){return U.call(b,a)>=0!==c})}function e(a,b){for(;(a=a[b])&&1!==a.nodeType;);return a}function f(a){var b=oa[a]={};return _.each(a.match(na)||[],function(a,c){b[c]=!0}),b}function g(){Z.removeEventListener("DOMContentLoaded",g,!1),a.removeEventListener("load",g,!1),_.ready()}function h(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=_.expando+h.uid++}function i(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(ua,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:ta.test(c)?_.parseJSON(c):c}catch(e){}sa.set(a,b,c)}else c=void 0;return c}function j(){return!0}function k(){return!1}function l(){try{return Z.activeElement}catch(a){}}function m(a,b){return _.nodeName(a,"table")&&_.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function n(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function o(a){var b=Ka.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function p(a,b){for(var c=0,d=a.length;d>c;c++)ra.set(a[c],"globalEval",!b||ra.get(b[c],"globalEval"))}function q(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(ra.hasData(a)&&(f=ra.access(a),g=ra.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)_.event.add(b,e,j[e][c])}sa.hasData(a)&&(h=sa.access(a),i=_.extend({},h),sa.set(b,i))}}function r(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&_.nodeName(a,b)?_.merge([a],c):c}function s(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ya.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}function t(b,c){var d,e=_(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:_.css(e[0],"display");return e.detach(),f}function u(a){var b=Z,c=Oa[a];return c||(c=t(a,b),"none"!==c&&c||(Na=(Na||_("