From: Youngsoo Choi Date: Fri, 19 Mar 2021 01:48:26 +0000 (-0700) Subject: [Public][Service] Upgrade d2d app version as v1.0.1 X-Git-Tag: submit/tizen/20210319.160018^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93f8a4ffa77df1b6fc850f57eb143b10ed3f575c;p=platform%2Fframework%2Fweb%2Fwrtjs.git [Public][Service] Upgrade d2d app version as v1.0.1 This upgrades d2d app version as v1.0.1. Change-Id: I6c305c011537e026779634993a56fcaec1d02425 Signed-off-by: Youngsoo Choi --- diff --git a/d2d_app/about.html b/d2d_app/about.html new file mode 100644 index 00000000..43606467 --- /dev/null +++ b/d2d_app/about.html @@ -0,0 +1,15 @@ + + + + + + + + + +
+

Global Device Web Server v.0.1

+
+ + + diff --git a/d2d_app/client/client.html b/d2d_app/client/client.html index 1cad15a2..59c82985 100755 --- a/d2d_app/client/client.html +++ b/d2d_app/client/client.html @@ -1,27 +1,106 @@ - + - - - - Client + + + My Device App + + + + + + + + + -
-
-
-
- App List -
-
-
-
-
-
-
-
-
-
-
+
+
+
+ My Device App +
+
+ +
+
+ + + +
+
+
+ +
+ Instant Control + +
+
+
+
+ +
+ D2D on My Device +
+
+
+
+
+
+
+
My Device App
+
+ +
+
+
+ Customize widgets +
+
+ +
+ +
+
+
diff --git a/d2d_app/client/control.html b/d2d_app/client/control.html new file mode 100644 index 00000000..9fa5c965 --- /dev/null +++ b/d2d_app/client/control.html @@ -0,0 +1,196 @@ + + + + + + Home Tv App + + + + + +
+ +
+
+ Instant Control +
+
+ +
+
+ +
+ +
+
+
+
+
+
Remote Control
+
+
+
+ +
+ + + +
+
+
+
+ + VOL + +
+
+ + CH + +
+
+
+ + +
+ + +
+
+
+
+
+
+
+
+
Remote Control
+
+
+
+ +
+ + + +
+
+
+
+ + VOL + +
+
+ + CH + +
+
+
+ + + + + + + + + + + + +
+
+
+
+
+
+
+
+
Typing Control
+
+
+
+ +
+ + +
+
+
+
+
+
+
+
Media Control
+
+
+
+
+ +
+
+ -10s + + + + +10s +
+
+
+
+
+
+
+
Game
+
+
+
+
+
+ + + + +
+
+ + + + +
+
+
+
+
+
+
+
+ +
+ + diff --git a/d2d_app/client/css/app-remote-control-basic.css b/d2d_app/client/css/app-remote-control-basic.css new file mode 100644 index 00000000..f7d49c8d --- /dev/null +++ b/d2d_app/client/css/app-remote-control-basic.css @@ -0,0 +1,478 @@ +.app-remote-control { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 5px 0; + flex-direction: column; +} + +@media (max-height:641px) { + .app-home-buttons { + display: flex; + justify-content: space-between; + height: 28px; + padding: 0 20px; + } +} +@media (min-height:642px) { + .app-home-buttons { + display: flex; + justify-content: space-between; + height: 38px; + padding: 0 20px; + } +} + +.ui-icon-home::after { + mask-image: url(../images/control/ic_home.png); + -webkit-mask-image: url(../images/control/ic_home.png); + mask-size: 24px !important; + -webkit-mask-size: 24px !important; +} +.ui-icon-enter::after { + mask-size: 26px 18px; + mask-image: url(../images/control/ic_source.png); + -webkit-mask-size: 26px 18px !important; + -webkit-mask-image: url(../images/control/ic_source.png); +} +.ui-icon-backward::after { + mask-size: 25px 23px !important; + -webkit-mask-size: 25px 23px !important; + mask-image: url(../images/ic_back.png); + -webkit-mask-image: url(../images/ic_back.png); +} + +.app-volume-channel { + flex-direction: row; + width: calc(100% - 148px); + display: flex; + justify-content: space-between; +} +@media (max-height:641px) { + .app-volume-control { + display: flex; + flex-direction: column; + font-size: 16px; + background-image: linear-gradient(180deg, + transparent, transparent 25px, #ebebeb 25px, + #ebebeb 100px, transparent 100%); + width: 53px; + align-items: center; + height: 125px; + justify-content: space-between; + } +} +@media (min-height:642px) { + .app-volume-control { + display: flex; + flex-direction: column; + font-size: 16px; + background-image: linear-gradient(180deg, + transparent, transparent 25px, #ebebeb 25px, + #ebebeb 125px, transparent 100%); + width: 53px; + align-items: center; + height: 173px; + justify-content: space-between; + } +} +.app-btn-icon-volume-up { + background-image: url(../images/control/btn_plus.png); + background-size: 100%; + background-position-y: 2px; +} +.app-btn-icon-volume-up::after { + display: none; +} +.app-btn-icon-volume-down { + background-image: url(../images/control/btn_minus.png); + background-size: 100%; + background-position-y: 2px; +} +.app-btn-icon-volume-down::after { + display: none; +} +@media (max-height:641px) { + .app-channel-control { + display: flex; + flex-direction: column; + font-size: 16px; + background-image: linear-gradient(180deg, + transparent, transparent 25px, #ebebeb 25px, + #ebebeb 100px, transparent 100%); + width: 53px; + align-items: center; + height: 125px; + justify-content: space-between; + } +} +@media (min-height:642px) { + .app-channel-control { + display: flex; + flex-direction: column; + font-size: 16px; + background-image: linear-gradient(180deg, + transparent, transparent 25px, #ebebeb 25px, + #ebebeb 125px, transparent 100%); + width: 53px; + align-items: center; + height: 173px; + justify-content: space-between; + } +} + +.app-btn-icon-channel-up { + background-image: url(../images/control/btn_up.png); + background-size: 100%; + background-position-y: 2px; +} +.app-btn-icon-channel-up::after { + display: none; +} +.app-btn-icon-channel-down { + background-image: url(../images/control/btn_down.png); + background-size: 100%; + background-position-y: 2px; +} +.app-btn-icon-channel-down::after { + display: none; +} +@media (max-height:641px) { + .app-4way-direction { + display: grid; + grid-template-columns: 25px 1fr 25px; + grid-template-rows: 25px 1fr 25px; + grid-gap: 5px; + width: 100%; + height: 130px; + justify-items: center; + background-color: #ebebeb; + border-radius: 32px; + margin-top: 10px; + } +} +@media (min-height:642px) { + .app-4way-direction { + display: grid; + grid-template-columns: 25px 1fr 25px; + grid-template-rows: 25px 1fr 25px; + grid-gap: 5px; + width: 100%; + height: 210px; + justify-items: center; + background-color: #ebebeb; + border-radius: 32px; + margin-top: 10px; + } +} +.app-remote-control .app-4way-direction .ui-btn.ui-btn-flat.ui-btn-icon { + max-width: 100%; + width: 100%; + height: 100%; + min-width: 32px; +} + +.app-remote-control-icon { + background-color: var(--primary-color); + border-radius: 6px; + position: relative; +} + +.app-remote-control-icon::after{ + content: ""; + width: 100%; + height: 100%; + position: absolute; + background-color: var(--color-white); + mask-size: 100%; + mask-image: url(../images/control/tw_list_icon_connections.svg); + -webkit-mask-size: 100%; + -webkit-mask-image: url(../images/control/tw_list_icon_connections.svg); +} + +.app-4way-btn-up { + grid-column: 2 / 2; + grid-row: 1; + align-self: center; +} + +.app-4way-btn-left { + grid-column: 1 / 1; + grid-row: 2; + align-self: center; +} + +.app-4way-btn-right { + grid-column: 3 / 3; + grid-row: 2; + align-self: center; +} + +.app-4way-btn-down { + grid-column: 2 / 2; + grid-row: 3; + align-self: center; +} + +.app-4way-touchpad { + grid-column: 2 / 2; + grid-row: 2 / 2; + width: 100%; + border-radius: 28px; + background-color: #f4f4f4; +} + +.app-remote-num-pad { + display: grid; + grid-gap: 5px; + width: 100%; + justify-items: center; + border-radius: 28px; + margin-top: 10px; + overflow: hidden; + grid-template-columns: 1fr 1fr 1fr; +} +.app-remote-num-pad .ui-btn { + display: flex; + align-items: center; + justify-content: center; + color: var(--text-color); + width: 100% !important; + height: 100%; + background-color: #ebebeb; + border-radius: 0; +} +.app-num-pad-1 { + grid-column: 1 / 1; + grid-row: 1; +} +.app-num-pad-2 { + grid-column: 2 / 2; + grid-row: 1; +} +.app-num-pad-3 { + grid-column: 3 / 3; + grid-row: 1; +} +.app-num-pad-4 { + grid-column: 1 / 1; + grid-row: 2; +} +.app-num-pad-5 { + grid-column: 2 / 2; + grid-row: 2; +} +.app-num-pad-6 { + grid-column: 3 / 3; + grid-row: 2; +} + +.app-remote-control .ui-btn.ui-btn-flat.ui-btn-icon { + width: 58px; + height: 58px; + min-width: 58px; +} +.ui-btn.ui-icon-right::after { + -webkit-transform: translate(-50%, -50%) rotateZ(-90deg); + -ms-transform: translate(-50%, -50%) rotate(-90deg); + transform: translate(-50%, -50%) rotateZ(-90deg); +} +.ui-btn.ui-icon-left::after { + -webkit-transform: translate(-50%, -50%) rotateZ(90deg); + -ms-transform: translate(-50%, -50%) rotate(90deg); + transform: translate(-50%, -50%) rotateZ(90deg); +} +.ui-btn.ui-btn-flat.ui-btn-icon::before { + width: 48px; + height: 48px; +} + +.app-border { + box-shadow: 0 0 0 0.25px var(--content-area-line-color) inset; +} + +/* Typing control */ +.app-typing-control-icon { + background-image: url(../images/control/squarcle_bg.png); + background-size: 100%; +} +.app-voice-button { + background-image: url(../images/control/default.png); + background-size: 100%; + width: 43px !important; + height: 43px !important; + display: inline-block; + max-width: 43px; + max-height: 43px; + background-repeat: no-repeat; + background-position: center; +} +.app-input-with-button { + display: flex; +} + +/* media control */ +.app-media-buttons { + display: flex; + align-items: center; + justify-content: space-between; + height: 51px; + color: var(--color-black); +} +.app-media-buttons .ui-icon-prev::after { + mask-image: url(../images/control/ic_function_media_prev.svg); + -webkit-mask-image: url(../images/control/ic_function_media_prev.svg); +} +.app-media-buttons .ui-icon-next::after { + mask-image: url(../images/control/ic_function_media_next.svg); + -webkit-mask-image: url(../images/control/ic_function_media_next.svg); + transform: translate(-50%, -50%); +} +.app-media-buttons .ui-icon-pause::after { + mask-image: url(../images/control/ic_function_media_stop.svg); + -webkit-mask-image: url(../images/control/ic_function_media_stop.svg); +} +.app-media-buttons .ui-icon-play::after { + mask-image: url(../images/control/ic_control1_right.png); + -webkit-mask-image: url(../images/control/ic_control1_right.png); + mask-size: 20px !important; + -webkit-mask-size: 20px !important; +} +.app-media-buttons .ui-btn:not(.ui-btn-icon) { + width: 50px !important; + line-height: 32px; + color: var(--color-black); + font-size: 17px; +} +.app-media-progress .ui-slider-handler::after { + content: attr(data-value); + position: absolute; + left: -20%; + bottom: -18px; + font-size: 12px; + color: #999999; +} +.app-media-control-icon { + background-image: url(../images/control/squarcle_bg.png); + background-size: 100%; +} + +/** game pad **/ +.app-game-4way-direction { + background-image: url("../images/control/control1_bg .png"); + width: 157px; + height: 157px; + background-position: center; + background-size: 100%; + display: inline-grid; + grid-template-columns: 48px 1fr 48px; + grid-template-rows: 48px 1fr 48px; +} +.app-game-4way-direction .ui-icon-up { + grid-column: 2; + grid-row: 1; +} +.app-game-4way-direction .ui-icon-left { + grid-column: 1 / 1; + grid-row: 2; +} +.app-game-4way-direction .ui-icon-right { + grid-column: 3 / 3; + grid-row: 2; +} +.app-game-4way-direction .ui-icon-down { + grid-column: 2; + grid-row: 3; +} +.app-game-4way-direction .ui-btn { + justify-self: center; +} +.app-game-4way-direction .ui-btn::after { + justify-self: center; + mask-size: 12px !important; + -webkit-mask-size: 12px !important; + transform: translate(-50%, -50%); +} + +.app-game-4way-direction .ui-icon-up::after { + mask-image: url(../images/control/ic_control1_top.png); + -webkit-mask-image: url(../images/control/ic_control1_top.png); +} +.app-game-4way-direction .ui-icon-down::after { + mask-image: url(../images/control/ic_control1_bottom.png); + -webkit-mask-image: url(../images/control/ic_control1_bottom.png); +} +.app-game-4way-direction .ui-icon-left::after { + mask-image: url(../images/control/ic_control1_left.png); + -webkit-mask-image: url(../images/control/ic_control1_left.png); +} +.app-game-4way-direction .ui-icon-right::after { + mask-image: url(../images/control/ic_control1_right.png); + -webkit-mask-image: url(../images/control/ic_control1_right.png); +} +.app-game-4buttons { + width: 157px; + height: 157px; + background-position: center; + background-size: 100%; + display: inline-grid; + grid-template-columns: 58px 35px 58px; + grid-template-rows: 58px 35px 58px; +} +.app-game-4buttons .ui-btn.ui-btn-icon { + background-image: url(../images/control/control2_bg\ .png); + background-size: 100%; + background-position-y: 2px; + min-width: 58px; + min-height: 58px; +} +.app-game-4buttons-Y { + grid-column: 2; + grid-row: 1; + justify-self: center; +} +.app-game-4buttons-X { + grid-column: 1; + grid-row: 2; + align-self: center; +} +.app-game-4buttons-B { + grid-column: 3; + grid-row: 2; + align-self: center; +} +.app-game-4buttons-A { + grid-column: 2; + grid-row: 3; + justify-self: center; +} + +.app-game-4buttons .ui-btn.ui-btn-icon::after { + mask-image: none; + -webkit-mask-image: none; + background-color: transparent; + font-size: 16px; + text-align: center; + height: auto; +} +.app-game-4buttons-Y::after { + content: "Y"; + color: #ffb100; +} +.app-game-4buttons-X::after { + content: "X"; + color: #18a3ff; +} +.app-game-4buttons-B::after { + content: "B"; + color: #ed3c36; +} +.app-game-4buttons-A::after { + content: "A"; + color: #67ce2b; +} +.app-game-control-icon { + background-image: url(../images/control/squarcle_bg.png); + background-size: 100%; +} \ No newline at end of file diff --git a/d2d_app/client/css/pincode.css b/d2d_app/client/css/pincode.css new file mode 100644 index 00000000..7b5dbf80 --- /dev/null +++ b/d2d_app/client/css/pincode.css @@ -0,0 +1,302 @@ +body { + height: 100%; + background: white; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + font-family: Open Sans; +} + +body.wrong { + -webkit-animation: bg-red 1s ease-in; + animation: bg-red 1s ease-in; +} + +body.correct { + -webkit-animation: bg-green 1s ease-in; + animation: bg-green 1s ease-in; +} + +#pin { + background: #212121; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + padding: 1em; + border-radius: .3em; + box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); + margin-top: 12px; + color: rgba(255, 255, 255, 1.0); +} + +.dots { + width: 50%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + padding: 1em; + padding-top: 3em; +} + +.dot { + position: relative; + background: rgba(255, 255, 255, 0.2); + border-radius: 0.8em; + width: 0.8em; + height: 0.8em; + -webkit-transform: scale3d(0.7, 0.7, 0.7); + transform: scale3d(0.7, 0.7, 0.7); +} + +.dot.active { + -webkit-animation: growDot .5s ease; + animation: growDot .5s ease; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; +} + +.dot.wrong { + -webkit-animation: wrong .9s ease; + animation: wrong .9s ease; +} + +.dot.correct { + -webkit-animation: correct .9s ease; + animation: correct .9s ease; +} + +#pin p { font-size: 1.0em; } + +.numbers { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-flow: row wrap; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + align-content: flex-end; + margin: 2em 0; +} + +.number { + position: relative; + width: 2.5em; + height: 2.5em; + margin: 0.3em; + border-radius: 2.5em; + border: 2px solid rgba(255, 255, 255, 0); + text-align: center; + line-height: 2.5em; + font-weight: 400; + font-size: 1.8em; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-transition: all .5s ease; + transition: all .5s ease; +} + +.number:hover { color: rgba(255, 255, 255, 0.5); } + +.number:hover:before { border: 2px solid rgba(255, 255, 255, 0.5); } + +.number:before { + content: ""; + position: absolute; + left: -2px; + width: 2.5em; + height: 2.5em; + border: 2px solid rgba(255, 255, 255, 0.1); + border-radius: 2.5em; + -webkit-transition: all .5s ease; + transition: all .5s ease; +} + +.number.grow:before { + -webkit-animation: grow .4s ease; + animation: grow .4s ease; +} + +@-webkit-keyframes +growDot { + 100% { + background: white; + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } +} + +@keyframes +growDot { + 100% { + background: white; + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } +} + +@-webkit-keyframes +grow { + 50% { + -webkit-transform: scale3d(1.5, 1.5, 1.5); + transform: scale3d(1.5, 1.5, 1.5); + } + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes +grow { + 50% { + -webkit-transform: scale3d(1.5, 1.5, 1.5); + transform: scale3d(1.5, 1.5, 1.5); + } + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@-webkit-keyframes +wrong { + 20% { + background: crimson; + } + 40% { + -webkit-transform: translate(-15px, 0); + transform: translate(-15px, 0); + } + 60% { + -webkit-transform: translate(10px, 0); + transform: translate(10px, 0); + } + 80% { + -webkit-transform: translate(-5px, 0); + transform: translate(-5px, 0); + } +} + +@keyframes +wrong { + 20% { + background: crimson; + } + 40% { + -webkit-transform: translate(-15px, 0); + transform: translate(-15px, 0); + } + 60% { + -webkit-transform: translate(10px, 0); + transform: translate(10px, 0); + } + 80% { + -webkit-transform: translate(-5px, 0); + transform: translate(-5px, 0); + } +} + +@-webkit-keyframes +correct { + 20% { + background: #1c72ad; + } + 40% { + -webkit-transform: translate(0, -15px); + transform: translate(0, -15px); + } + 60% { + -webkit-transform: translate(0, 10px); + transform: translate(0, 10px); + } + 80% { + -webkit-transform: translate(0, -5px); + transform: translate(0, -5px); + } +} + +@keyframes +correct { + 20% { + background: #1c72ad; + } + 40% { + -webkit-transform: translate(0, -15px); + transform: translate(0, -15px); + } + 60% { + -webkit-transform: translate(0, 10px); + transform: translate(0, 10px); + } + 80% { + -webkit-transform: translate(0, -5px); + transform: translate(0, -5px); + } +} + +@-webkit-keyframes +bg-red { + 50% { + background: crimson; + } +} + +@keyframes +bg-red { + 50% { + background: crimson; + } +} + +@-webkit-keyframes +bg-green { + 50% { + background: #1c72ad; + } +} + +@keyframes +bg-green { + 50% { + background: #1c72ad; + } +} diff --git a/d2d_app/client/css/style.css b/d2d_app/client/css/style.css index 583efdeb..c9c17505 100755 --- a/d2d_app/client/css/style.css +++ b/d2d_app/client/css/style.css @@ -1,116 +1,65 @@ -html, body { - width: 100%; - height: 100%; - margin: 0 auto; - padding: 0; +.app-image-grid { + margin: auto; + display: grid; + grid-template-columns: repeat(3, 100px [col-start]); + grid-template-rows: auto; + gap: 10px; + justify-items: center; + justify-content: center; + padding: 20px; } -#container { - width: 100%; - height: 100%; - display: table; +.app-image-big-grid { + margin: auto; + display: grid; + grid-template-columns: repeat(1, 100px [col-start]); + grid-template-rows: auto; + gap: 10px; + justify-items: center; + justify-content: center; + padding: 20px; } -.page { - width: 100%; - height: 100%; - padding-top: 50px; - display: block; +.app-icon-img { + width: 100px; + height: 100px; } -.header { - position: relative; - width: 100%; - height: 50px; - margin-top: -50px; - background-color: rgba(0, 80, 179, 1); - z-index: 999; - display: table; +.app-icon-big-img { + width: 150px; + height: 150px; } -.text-header { - color: #ffffff; - font-size: 1.5em; - vertical-align: middle; - text-align: center; - display: table-cell; +.app-btn-icon-burger { + margin-left: 20px; + margin-right: 12px; } -.contents { - width: 100%; - height: 100%; -} - -.contents-name-detail { - font-size: 1.5em; - padding: 10px; -} - -.icon-folder { - vertical-align: middle; -} - -.detail { - width: 100%; - height: 100%; +.app-btn-icon-burger::after { + -webkit-mask-image: url(../images/Hamburger_icon.svg); + mask-image: url(../images/Hamburger_icon.svg); } -.result-table { - display: table; - text-align: center; - width: 100%; - height: 100%; - vertical-align: middle; -} - -.result-table-row { - display: table; +.app-dummy-payment input { + display: block; + font-size: 18px; + padding: 8px; + margin: 4px 0; + border-radius: 8px; + border: 1px solid #ddd; + box-sizing: border-box; width: 100%; - height: 60px; - vertical-align: middle; - border-bottom: 1px solid black; -} - -.result-table-error { - display: table-cell; - font-size: 1.8em; - vertical-align: middle; - text-align: center; } - -.d2dApp-detail { - display: table-cell; - font-size: 1.2em; - vertical-align: middle; - text-align: left; - padding-left: 10px; - width: 100%; +.app-dummy-payment input.ui-inline { + width: auto; + display: inline; } -.text-error { - text-align: center; - color: rgba(0, 0, 0, 1); - font-size: 1.5em; +body { + /*disable-pull-to-refresh-effect*/ + overscroll-behavior: contain; } -.spinner { - position:absolute; - top:50%; - left:50%; - transform:translate(-50%, -50%); +.app-display-none { display: none; } - -.spinner-img { - border: 16px solid #f3f3f3; - border-top: 16px solid #3498db; - border-radius: 50%; - width: 120px; - height: 120px; - animation: spin 2s linear infinite; -} - -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} diff --git a/d2d_app/client/images/Hamburger_icon.svg b/d2d_app/client/images/Hamburger_icon.svg new file mode 100644 index 00000000..233bf217 --- /dev/null +++ b/d2d_app/client/images/Hamburger_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/d2d_app/client/images/control/btn_down.png b/d2d_app/client/images/control/btn_down.png new file mode 100644 index 00000000..d00eaefd Binary files /dev/null and b/d2d_app/client/images/control/btn_down.png differ diff --git a/d2d_app/client/images/control/btn_minus.png b/d2d_app/client/images/control/btn_minus.png new file mode 100644 index 00000000..69e5b88e Binary files /dev/null and b/d2d_app/client/images/control/btn_minus.png differ diff --git a/d2d_app/client/images/control/btn_plus.png b/d2d_app/client/images/control/btn_plus.png new file mode 100644 index 00000000..303aacf3 Binary files /dev/null and b/d2d_app/client/images/control/btn_plus.png differ diff --git a/d2d_app/client/images/control/btn_up.png b/d2d_app/client/images/control/btn_up.png new file mode 100644 index 00000000..f7012e35 Binary files /dev/null and b/d2d_app/client/images/control/btn_up.png differ diff --git a/d2d_app/client/images/control/control1_bg .png b/d2d_app/client/images/control/control1_bg .png new file mode 100644 index 00000000..5ebcc5b6 Binary files /dev/null and b/d2d_app/client/images/control/control1_bg .png differ diff --git a/d2d_app/client/images/control/control2_bg .png b/d2d_app/client/images/control/control2_bg .png new file mode 100644 index 00000000..67920ef0 Binary files /dev/null and b/d2d_app/client/images/control/control2_bg .png differ diff --git a/d2d_app/client/images/control/cta/oval/default.png b/d2d_app/client/images/control/cta/oval/default.png new file mode 100644 index 00000000..43818ea0 Binary files /dev/null and b/d2d_app/client/images/control/cta/oval/default.png differ diff --git a/d2d_app/client/images/control/default.png b/d2d_app/client/images/control/default.png new file mode 100644 index 00000000..43818ea0 Binary files /dev/null and b/d2d_app/client/images/control/default.png differ diff --git a/d2d_app/client/images/control/ic_control1_bottom.png b/d2d_app/client/images/control/ic_control1_bottom.png new file mode 100644 index 00000000..a9b8d11c Binary files /dev/null and b/d2d_app/client/images/control/ic_control1_bottom.png differ diff --git a/d2d_app/client/images/control/ic_control1_left.png b/d2d_app/client/images/control/ic_control1_left.png new file mode 100644 index 00000000..a26d81df Binary files /dev/null and b/d2d_app/client/images/control/ic_control1_left.png differ diff --git a/d2d_app/client/images/control/ic_control1_right.png b/d2d_app/client/images/control/ic_control1_right.png new file mode 100644 index 00000000..657944d7 Binary files /dev/null and b/d2d_app/client/images/control/ic_control1_right.png differ diff --git a/d2d_app/client/images/control/ic_control1_top.png b/d2d_app/client/images/control/ic_control1_top.png new file mode 100644 index 00000000..1ffd3922 Binary files /dev/null and b/d2d_app/client/images/control/ic_control1_top.png differ diff --git a/d2d_app/client/images/control/ic_function_media_next.svg b/d2d_app/client/images/control/ic_function_media_next.svg new file mode 100644 index 00000000..e3be188f --- /dev/null +++ b/d2d_app/client/images/control/ic_function_media_next.svg @@ -0,0 +1,15 @@ + + + + SVG/ic/ic_function_media_next + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/d2d_app/client/images/control/ic_function_media_prev.svg b/d2d_app/client/images/control/ic_function_media_prev.svg new file mode 100644 index 00000000..3375154f --- /dev/null +++ b/d2d_app/client/images/control/ic_function_media_prev.svg @@ -0,0 +1,15 @@ + + + + SVG/ic/ic_function_media_prev + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/d2d_app/client/images/control/ic_function_media_stop.svg b/d2d_app/client/images/control/ic_function_media_stop.svg new file mode 100644 index 00000000..941c24b3 --- /dev/null +++ b/d2d_app/client/images/control/ic_function_media_stop.svg @@ -0,0 +1,10 @@ + + + + SVG/ic/ic_function_media_stop + Created with Sketch. + + + + + \ No newline at end of file diff --git a/d2d_app/client/images/control/ic_home.png b/d2d_app/client/images/control/ic_home.png new file mode 100644 index 00000000..d0127de1 Binary files /dev/null and b/d2d_app/client/images/control/ic_home.png differ diff --git a/d2d_app/client/images/control/ic_source.png b/d2d_app/client/images/control/ic_source.png new file mode 100644 index 00000000..a7cda546 Binary files /dev/null and b/d2d_app/client/images/control/ic_source.png differ diff --git a/d2d_app/client/images/control/squarcle_bg.png b/d2d_app/client/images/control/squarcle_bg.png new file mode 100644 index 00000000..e101dffd Binary files /dev/null and b/d2d_app/client/images/control/squarcle_bg.png differ diff --git a/d2d_app/client/images/control/tw_list_icon_connections.svg b/d2d_app/client/images/control/tw_list_icon_connections.svg new file mode 100644 index 00000000..a08d6b63 --- /dev/null +++ b/d2d_app/client/images/control/tw_list_icon_connections.svg @@ -0,0 +1,17 @@ + + + +settings/main_icon/01_connections copy +Created with Sketch. + + + + + + diff --git a/d2d_app/client/images/folder.png b/d2d_app/client/images/folder.png deleted file mode 100755 index c8395f54..00000000 Binary files a/d2d_app/client/images/folder.png and /dev/null differ diff --git a/d2d_app/client/images/ic_back.png b/d2d_app/client/images/ic_back.png new file mode 100644 index 00000000..ab49ba85 Binary files /dev/null and b/d2d_app/client/images/ic_back.png differ diff --git a/d2d_app/client/images/icon.png b/d2d_app/client/images/icon.png new file mode 100755 index 00000000..9765b1bd Binary files /dev/null and b/d2d_app/client/images/icon.png differ diff --git a/d2d_app/client/images/tw_list_icon_wallpaper.svg b/d2d_app/client/images/tw_list_icon_wallpaper.svg new file mode 100644 index 00000000..bb273447 --- /dev/null +++ b/d2d_app/client/images/tw_list_icon_wallpaper.svg @@ -0,0 +1,17 @@ + + + +settings/main_icon/05_wallpaper copy +Created with Sketch. + + + + + + + + diff --git a/d2d_app/client/invited.html b/d2d_app/client/invited.html new file mode 100644 index 00000000..332e2120 --- /dev/null +++ b/d2d_app/client/invited.html @@ -0,0 +1,31 @@ + + + + + + + My Device App + + + + + + + + +
+
+
+
+
+
+

Would you like to join the room?

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/d2d_app/client/js/actions.js b/d2d_app/client/js/actions.js new file mode 100644 index 00000000..b158f2c4 --- /dev/null +++ b/d2d_app/client/js/actions.js @@ -0,0 +1,58 @@ +const serverPort = 9000; +const serverURL = window.location.protocol + '//' + window.location.hostname; + +class Actions { + /** + * Launch App on TV + * This method creates function for onclick listener + * @param {string} appPkgID + * @param {string} appAppID + * @param {Function} callback + * @returns {Function} + */ + + launchAppOnTV(appPkgID, appAppID, callback) { + const xhr = new XMLHttpRequest(); + + var self = this; + var retFunc = function() { + var data = { + appPkgID: appPkgID, + appAppID: appAppID + }; + self.sendDataToApp(appAppID, data, callback); + }; + return retFunc; + }; + + /** + * Send data to host + * @param {string} appID + * @param {Object} data + * @param {Function} callback + */ + sendDataToApp(appID, data, callback) { + const xhr = new XMLHttpRequest(); + // add tv app id + data.appAppID = appID; + data.appPkgID = appID.replace(/\..+$/, ""); + + xhr.onreadystatechange = function() { + if (xhr.readyState === xhr.DONE) { + if (xhr.status === 200 || xhr.status === 201) { + var response = JSON.parse(xhr.responseText); + if (typeof callback === "function") { + callback(response); + } + } else { + console.error(xhr.responseText); + } + } + } + xhr.open('POST', serverURL + ':' + serverPort + '/app'); + xhr.setRequestHeader('Content-Type', 'application/json'); + xhr.send(JSON.stringify(data)); + }; +} + +export default Actions; diff --git a/d2d_app/client/js/app.js b/d2d_app/client/js/app.js new file mode 100644 index 00000000..d717a9a2 --- /dev/null +++ b/d2d_app/client/js/app.js @@ -0,0 +1,513 @@ +import Storage from "./clipping-storage.js"; +import Actions from './actions.js'; +import { openAppWindow } from './myApps.js'; + +const moduleapp = {}; + +(function () { + "use strict"; + var tau = window.tau, + HomeApp = function () { + this.version = "0.1"; + this.appsList = []; + }, + prototype = HomeApp.prototype, + storage = new Storage(), + actions = new Actions(), + appsList = [], + socket = null, + homeApp; + + const defaultList = [], + getAppsList = new Promise((resolve, reject) => { + const requestURL = "client/updateWebclip"; + + fetch(requestURL) + .then((response) => response.json()) + .then((response) => { + //addWSListener(data.wsPort); + resolve(response.data.apps); + }) + .catch((e) => { + reject(e); + }) + }); + + function updateAppsList(message) { + if (message.type === "full") { + return updateAppsListFull(message.data); + } else if (message.type === "diff") { + updateAppsListDiff(message.data); + return true; + } else { + console.warn("app.js: unsupported type of applist."); + } + return false; + } + + function updateAppsListDiff(apps) { + apps.forEach(function (remoteApp) { + if (remoteApp.action === "add") { // add (or update if app already added) + let localApp = appsList.filter(function (localApp) { + return remoteApp.appID === localApp.appID; + })[0]; + delete remoteApp.action; + + if (!localApp) { // add new + appsList.push(remoteApp); + } else { // update local app + /** + * @todo + * Which properties we need update + */ + localApp.isActive = remoteApp.isActive; + } + } else if (remoteApp.action === "remove") { // remove local app + appsList = appsList.filter(function (localApp) { + return remoteApp.appID !== localApp.appID; + }); + } else { + console.warn("Unsupported action:", remoteApp.action); + } + + }); + + updateOrderOfApplist(); + } + + function updateOrderOfApplist() { + var change = false, + currentOrder = ""; + + currentOrder = appsList.reduce(function (prev, app) { + return prev + app.appID; + }, ""); + + // check apps order + appsList = appsList.sort(function (app1, app2) { + return (app1.isActive) ? + (app2.isActive) ? 0 : -1 : 1 + }); + + // order has been changed + if (currentOrder !== appsList.reduce(function (prev, app) { + return prev + app.appID; + }, "")) { + change = true; + } + + return change; + } + + function updateAppsListFull(apps) { + var change = false, + appsCount = appsList.length; + + // remove app from local apps list if not exists on remote host + appsList = appsList.filter(function (localApp) { + return apps.some(function (remoteApp) { + return remoteApp.appID === localApp.appID; + }); + }); + + if (appsCount !== appsList.length) { + change = true; + } + + // filter app which should be add to local apps list + const added = apps.filter(function (remoteApp) { + return !appsList.some(function (localApp) { + return localApp.appID === remoteApp.appID; + }); + }); + + if (added.length) { + change = true; + } + + // add apps to local apps list + added.forEach(function (remoteApp) { + appsList.push(remoteApp); + }); + + // update active items + appsList.forEach(function (localApp) { + apps.forEach(function (remoteApp) { + if (remoteApp.appID === localApp.appID) { + if (localApp.isActive !== remoteApp.isActive) { + localApp.isActive = remoteApp.isActive; + change = true; + } + } + }) + }); + + if (updateOrderOfApplist()) { + change = true; + }; + + return change; + } + function onWSMessage(message) { + if (updateAppsList(message)) { + tau.log("change"); + storage.refreshStorage(Storage.elements.APPSLIST, appsList); + + updateWebClipsUI(); + updateWebClipListPopup(); + } else { + tau.log("nothing change"); + } + } + async function getManifests() { + const promisesList = [], + indexesList = []; + + let responses = []; + + appsList.forEach(function (app, appIndex) { + app.webClipsList.forEach(function (webClip, webClipIndex) { + promisesList.push( + fetch(webClip.url + "\\manifest.json") + ); + indexesList.push({ appIndex: appIndex, webClipIndex: webClipIndex }); + }); + }); + + responses = await Promise.allSettled(promisesList); + + for (let responseIndex = 0; responseIndex < responses.length; responseIndex++) { + const response = responses[responseIndex]; + + if (response.status === "rejected" || !response.value.ok) { + appsList[indexesList[responseIndex].appIndex].webClipsList.splice(indexesList[responseIndex].webClipIndex, 1); + } else { + const contentPromise = await response.value.json(); + + appsList[indexesList[responseIndex].appIndex].webClipsList[indexesList[responseIndex].webClipIndex].manifest = contentPromise; + } + } + } + + function changeTheme(event) { + tau.theme.setTheme(event.target.value); + } + + function onPopupSubmit() { + appsList.forEach(function (app) { + app.webClipsList.forEach(function (webclip) { + const webClipName = getWebClipName(webclip.url), + checkbox = document.getElementById("popup-checkbox-" + webClipName); + + webclip.isSelected = checkbox.checked; + }) + }); + storage.refreshStorage(Storage.elements.APPSLIST, appsList); + + updateWebClipsUI(); + tau.history.back(); + } + + /** + * Click button event handler + * Opens drawer + */ + function onButtonClick() { + var drawerWidget = tau.widget.Drawer(document.querySelector(".ui-drawer")); + + drawerWidget.open(); + } + function onDone(result) { + console.log("onDone", result); + } + function createWebClipCard(webClip, appID) { + var card = document.createElement("div"), + webClipUrl = webClip.url; + + // add slash for name of webClip + if (!webClipUrl.match(/\/$/)) { + webClipUrl += "/"; + } + webClipUrl += "webclip.html"; + + card.classList.add("ui-card"); + card.setAttribute("data-src", webClipUrl); + card.addEventListener("webclip-message", function (ev) { + if (ev.detail.remoteui) + actions.sendDataToApp(appID, ev.detail, openAppWindow); + else + actions.sendDataToApp(appID, ev.detail, onDone); + }); + + return card; + } + + + homeApp = new HomeApp(); + + prototype.createControlCard = function (data) { + var controlCard = document.createElement("div"), + title = document.createElement("span"), + icon = document.createElement("div"), + img = document.createElement("img"), + a = document.createElement("a"); + + controlCard.classList.add("ui-content-area"); + icon.classList.add("ui-icon"); + title.classList.add("ui-title"); + title.textContent = data.title; + img.src = data.icon; + a.href = data.href || "#next-control"; + a.setAttribute("data-style", "flat"); + a.setAttribute("data-inline", true); + a.setAttribute("data-icon", "next"); + a.classList.add("ui-btn"); + + icon.appendChild(img); + + controlCard.appendChild(icon); + controlCard.appendChild(title); + controlCard.appendChild(a); + + return controlCard; + } + + prototype.addControlCard = function (data) { + var controlCard = this.createControlCard(data), + appBarElement = document.querySelector(".ui-page-active header"), + appBar = tau.widget.Appbar(appBarElement); + + controlCard.setAttribute("data-title", data.title); + + appBar.addInstantContainer(controlCard); + } + + prototype.removeControlCard = function (card) { + var appBarElement = document.querySelector(".ui-page-active header"), + appBar = tau.widget.Appbar(appBarElement); + + appBar.removeInstantContainer(card); + } + + function updateWebClipsUI() { + var webclipsContainer = document.getElementById("web-clips"), + // get Cards elements and convert NodeList to array + currentWebClipsCards = [].slice.call(webclipsContainer.querySelectorAll(".ui-card[data-url],.ui-card[data-src]")), + // list of webClips url in order + webClipsUrlList = appsList.reduce(function (prev, app) { + return prev.concat( + app.webClipsList.filter((webClip) => webClip.isSelected) + .map((webClip) => webClip.url)); + }, []); + + // remove card + currentWebClipsCards.forEach(function (card) { + const found = webClipsUrlList.filter(function (webClipUrl) { + return card.dataset.url && card.dataset.url.indexOf(webClipUrl) > -1 || + card.dataset.src && card.dataset.src.indexOf(webClipUrl) > -1; + }); + + // remove card from UI if not exists on list + if (found.length === 0) { + card.parentElement.removeChild(card); + } + }); + + // add card + appsList.forEach(function (app) { + app.webClipsList.forEach((webClip) => { + const found = currentWebClipsCards.filter(function (card) { + return card.dataset.url && card.dataset.url.indexOf(webClip.url) > -1 || + card.dataset.src && card.dataset.src.indexOf(webClip.url) > -1; + }); + + if (found.length === 0) { + if (webClip.isSelected) { + webclipsContainer.appendChild( + createWebClipCard(webClip, app.appID) + ); + } + } + }); + }); + + // set proper order of cards + // @todo change inline styles to css class after merge HomeApp branches + webclipsContainer.style.display = "flex"; + webclipsContainer.style.flexDirection = "column"; + currentWebClipsCards = [].slice.call(webclipsContainer.querySelectorAll(".ui-card[data-url],.ui-card[data-src]")); + + webClipsUrlList.forEach(function (url, order) { + const card = currentWebClipsCards.filter(function (card) { + return card.dataset.url && card.dataset.url.indexOf(url) > -1 || + card.dataset.src && card.dataset.src.indexOf(url) > -1; + })[0]; + + if (card) { + card.style.order = order; + } + }); + + // add/remove mini control cards + appsList.forEach(function (app) { + app.webClipsList.forEach((webClip) => { + if (webClip.manifest && webClip.manifest.cardType === "control") { + if (webClip.isSelected) { + if (!document.querySelector("[data-title='" + webClip.manifest.description + "']")) { + homeApp.addControlCard({ + title: webClip.manifest.description, + href: "#open-control-card", + icon: "images/Icon.png" + } + ); + } + } else if (document.querySelector("[data-title='" + webClip.manifest.description + "']")) { + // remove mini controll card + homeApp.removeControlCard(document.querySelector("[data-title='" + webClip.manifest.description + "']")); + } + } + }); + }); + + tau.engine.createWidgets(webclipsContainer); + } + + //TODO: provide mechanism for getting web clip name from webClip meta data + // and separate from getting ID + function getWebClipName(webClip) { + // remove all text to the last \ + return webClip.replace(/.*\//, ""); + } + + function updateWebClipListPopup() { + + var popupList = document.getElementById("popup-list"); + + // remove previous li items + while (popupList.firstChild) { + popupList.firstChild.remove() + } + + appsList.forEach(function (app) { + app.webClipsList.forEach(function (webclip) { + var li = document.createElement("li"), + input = document.createElement("input"), + label = document.createElement("label"), + webClipName = getWebClipName(webclip.url); + + li.classList.add("ui-li-has-checkbox"); + li.classList.add("ui-group-index"); + + input.setAttribute("type", "checkbox"); + input.setAttribute("id", "popup-checkbox-" + webClipName); + + label.setAttribute("for", "popup-checkbox-" + webClipName); + label.classList.add("ui-li-text"); + label.innerHTML = webclip.manifest && webclip.manifest.description || webClipName; + + li.appendChild(input); + li.appendChild(label); + popupList.appendChild(li); + }); + }); + + tau.engine.createWidgets(popupList); + + appsList.forEach(function (app) { + app.webClipsList.forEach(function (webclip) { + if (webclip.isSelected) { + const webClipName = getWebClipName(webclip.url), + checkbox = document.getElementById("popup-checkbox-" + webClipName); + + if (checkbox) { + checkbox.checked = true; + } + } + }); + }); + } + + function init() { + var themeChanger = document.querySelector("#theme-selector"), + page = document.querySelector(".ui-page"), + themeChangerButton = page.querySelector("#selector-opener"), + burgerButton = page.querySelector(".app-btn-icon-burger"), + popupButton = page.querySelector("#popup-submit"); + + themeChanger.addEventListener("change", changeTheme); + + themeChangerButton.addEventListener("vclick", function () { + var dropdownmenuWidget = tau.widget.DropdownMenu(themeChanger); + + dropdownmenuWidget.open(); + }); + + burgerButton.addEventListener("click", onButtonClick); + popupButton.addEventListener("click", onPopupSubmit); + + // use apps list from storage or default apps list if sth wrong + appsList = storage.readAllFromStorage(Storage.elements.APPSLIST); + + // check webclips on remote server + getAppsList.then((apps) => { + updateAppsListFull(apps); + }).catch((e) => { + console.warn("Error getting app lits: " + e.message); + if (appsList.length === 0) { + updateAppsListFull(defaultList); + } + }).finally(() => { + // check webclips access + getManifests().then(() => { + storage.refreshStorage(Storage.elements.APPSLIST, appsList); + updateWebClipsUI(); + updateWebClipListPopup(); + }); + }); + } + + function onPageBeforeShow(event) { + if (event.target.id === "main") { + init(); + } + } + + /** + * Map array of D2D apps to webclip list + * @param {Array} dataApps + */ + function d2dAppsToWebClipsList(dataApps) { + var result = []; + var webclips = []; + + dataApps.forEach(function (app) { + webclips = []; + if (app.webclip && app.webclip.manifest) { + webclips.push({ + url: 'client/webclip/' + app.webclip.manifest.name, + isSelected: true + }); + } + result.push({ + appID: app.d2dApp.appAppID, + pkgID: app.d2dApp.appPkgID, + isInstalled: true, + isActive: false, + webClipsList: webclips + }); + }); + return result; + } + + document.addEventListener("pagebeforeshow", onPageBeforeShow); + moduleapp.onWSMessage = onWSMessage; + moduleapp.d2dAppsToWebClipsList = d2dAppsToWebClipsList; +}()); + +export function UpdateWebClip(message) { + var data = { + type: "full", + data: moduleapp.d2dAppsToWebClipsList(message) + } + moduleapp.onWSMessage(data); +}; diff --git a/d2d_app/client/js/client.js b/d2d_app/client/js/client.js index ea2b5910..3e1a6a10 100755 --- a/d2d_app/client/js/client.js +++ b/d2d_app/client/js/client.js @@ -1,134 +1,5 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -"use strict"; - -const serverPort = 9000; -const serverURL = window.location.protocol + '//' + window.location.hostname; -(function() { - var xhr ; - function emptyElement(elm) { - while (elm.firstChild) { - elm.removeChild(elm.firstChild); - } - return elm; - } - - function showListView(dataArray) { - var objResult = emptyElement(document.querySelector("#detail-main")), - objTable, - objRow, - objCol, - i, - prop; - - objTable = document.createElement("div"); - objTable.className = "result-table"; - - if (dataArray.length > 0) { - for (i = 0; i < dataArray.length; i++) { - objRow = document.createElement("div"); - - objRow.className = "result-table-row"; - for (prop in dataArray[i]) { - if (dataArray[i].hasOwnProperty(prop)) { - objCol = document.createElement("div"); - objCol.className = prop + "-detail"; - if (dataArray[i][prop].hasOwnProperty("appName")) { - objCol.appendChild(document.createTextNode(dataArray[i][prop].appName)); - } - objCol.addEventListener("click", sendAppID(dataArray[i][prop].appPkgID, dataArray[i][prop].appAppID)); - objRow.appendChild(objCol); - } - } - objTable.appendChild(objRow); - } - } else { - objRow = document.createElement("div"); - objRow.className = "result-table-error"; - objRow.appendChild(document.createTextNode("No Data")); - objTable.appendChild(objRow); - } - - objResult.appendChild(objTable); - } - - function showList() { - xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - if (xhr.readyState === xhr.DONE) { - if (xhr.status === 200 || xhr.status === 201) { - showListView(JSON.parse(xhr.responseText)); - } else { - console.error(xhr.responseText); - } - } - }; - xhr.open('GET', serverURL + ':' + serverPort + '/appList'); - xhr.send(); - } - - function sendAppID(appPkgID, appAppID) { - var retFunc = function() { - var data = { - appPkgID: appPkgID, - appAppID: appAppID - }; - xhr.onreadystatechange = function() { - if (xhr.readyState === xhr.DONE) { - if (xhr.status === 200 || xhr.status === 201) { - var res = JSON.parse(xhr.responseText); - document.getElementById("page-main").style.display = "none"; - document.getElementById("spinner-main").style.display = "block"; - var timer = setTimeout(function(){ - clearTimeout(timer); - document.getElementById("page-main").style.display = "block"; - document.getElementById("spinner-main").style.display = "none"; - window.open(serverURL + ':' + res.port + '/app', 'newWindow'); - }, 1000); - } else { - console.error(xhr.responseText); - } - } - } - xhr.open('POST', serverURL + ':' + serverPort + '/app'); - xhr.setRequestHeader('Content-Type', 'application/json'); - xhr.send(JSON.stringify(data)); - }; - return retFunc; - } - - function init() { - var eventSource = new EventSource(serverURL + ':' + serverPort + '/updateAppList'); - eventSource.addEventListener('message', evt => { - showListView(JSON.parse(evt.data)); - }, false); - eventSource.addEventListener('open', evt => { - console.log("Connected to..."); - }, false); - eventSource.addEventListener('error', evt => { - if (evt.target.readyState == EventSource.CLOSED) { - console.log("Disconnected from..."); - } else if (evt.target.readyState == EventSource.CONNECTING) { - console.log('Connecting to...'); - } - }, false); - showList(); - } - - /** +(function () { + /** * Back key event handler */ window.addEventListener("tizenhwkey", function (ev) { @@ -156,7 +27,4 @@ const serverURL = window.location.protocol + '//' + window.location.hostname; } } }); - - window.onload = init; }()); - diff --git a/d2d_app/client/js/clipping-storage.js b/d2d_app/client/js/clipping-storage.js new file mode 100644 index 00000000..02af6245 --- /dev/null +++ b/d2d_app/client/js/clipping-storage.js @@ -0,0 +1,24 @@ +class Storage { + constructor() { + this.appsList = JSON.parse(localStorage.getItem("appsList")) || []; + } + + refreshStorage(element, data = []) { + this[element] = data; + localStorage.setItem(element, JSON.stringify(this[element])); + } + + writeToStorage(element, link) { + this[element].push(link); + localStorage.setItem(element, JSON.stringify(this[element])); + } + + readAllFromStorage(element) { + return this[element]; + } + +} + +Storage.elements = {APPSLIST: "appsList"}; + +export default Storage; \ No newline at end of file diff --git a/d2d_app/client/js/control.js b/d2d_app/client/js/control.js new file mode 100644 index 00000000..79f82ec8 --- /dev/null +++ b/d2d_app/client/js/control.js @@ -0,0 +1,211 @@ +const KeyCode = { + BACK: 9, + _1: 10, + _2: 11, + _3: 12, + _4: 13, + _5: 14, + _6: 15, + _7: 16, + _8: 17, + _9: 18, + _0: 19, + RETURN: 36, + HOME: 71, + VOLUME_DOWN: 75, + VOLUME_UP: 76, + CHANNEL_DOWN: 95, + CHANNEL_UP: 96, + UP: 111, + LEFT: 113, + RIGHT: 114, + DOWN: 116, + //POWER: 124, + EXIT: 182, +}; + +var websocket; + +(function () { + var page = document.getElementById("open-control-app-1"); + + function onPageShow() { + var x = window.innerWidth / 2; + var y = window.innerHeight / 2; + + var id; + var SERVER = -1; + var link = document.location.href; + var pkgId = "2FUI52kIJP"; + var wsUri = "ws://" + link.split("/")[2] + "/" + pkgId; + + websocket = new WebSocket(wsUri); + websocket.onmessage = function(evt) { + var json = JSON.parse(evt.data); + if (json.id == SERVER && json.type == "id") + id = json.data; + }; + + function sendMessage(type, data) { + var packet = {type: type, data: data, id: id}; + websocket.send(JSON.stringify(packet)); + } + + var volup= page.querySelector(".app-btn-icon-volume-up"), + voldown= page.querySelector(".app-btn-icon-volume-down"), + channelup= page.querySelector(".app-btn-icon-channel-up"), + channeldown= page.querySelector(".app-btn-icon-channel-down"), + up= page.querySelector(".app-4way-btn-up"), + down= page.querySelector(".app-4way-btn-down"), + right= page.querySelector(".app-4way-btn-right"), + left= page.querySelector(".app-4way-btn-left"), + enter= page.querySelector(".app-btn-enter"), + home= page.querySelector(".app-btn-home"), + backward= page.querySelector(".app-btn-backward"), + touchpad= page.querySelector(".app-4way-touchpad"), + num1 = page.querySelector(".app-num-pad-1"), + num2 = page.querySelector(".app-num-pad-2"), + num3 = page.querySelector(".app-num-pad-3"), + num4 = page.querySelector(".app-num-pad-4"), + num5 = page.querySelector(".app-num-pad-5"), + num6 = page.querySelector(".app-num-pad-6"), + num7 = page.querySelector(".app-num-pad-7"), + num8 = page.querySelector(".app-num-pad-8"), + num9 = page.querySelector(".app-num-pad-9"), + num0 = page.querySelector(".app-num-pad-0"), + mediaProgress = page.querySelector(".app-media-progress input"), + progressHandler = page.querySelector(".app-media-progress .ui-slider-handler"), + labelMin = page.querySelector(".app-media-progress .ui-slider-label-min"), + labelMax = page.querySelector(".app-media-progress .ui-slider-label-max"); + + volup.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.VOLUME_UP}); + }); + voldown.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.VOLUME_DOWN}); + }); + channelup.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.CHANNEL_UP}); + }); + channeldown.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.CHANNEL_DOWN}); + }); + up.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.UP}); + }); + down.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.DOWN}); + }); + right.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.RIGHT}); + }); + left.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.LEFT}); + }); + enter.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.RETURN}); + }); + backward.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.BACK}); + }); + home.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode.HOME}); + }); + num1.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._1}); + }); + num2.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._2}); + }); + num3.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._3}); + }); + num4.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._4}); + }); + num5.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._5}); + }); + num6.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._6}); + }); + num7.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._7}); + }); + num8.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._8}); + }); + num9.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._9}); + }); + num0.addEventListener("click", function () { + sendMessage("keypress", {keycode: KeyCode._0}); + }); + + var ontouch = function (ev) { + switch (ev.type) { + case "click" : + sendMessage("click"); + break; + case "touchstart" : + x = ev.touches[0].pageX; + y = ev.touches[0].pageY; + break; + case "touchmove" : + ev.stopPropagation(); + // lock the default web engine behaviour eg. scrolling + ev.preventDefault(); + sendMessage("touchmove", {x: ev.touches[0].pageX - x, y: ev.touches[0].pageY - y}); + x = ev.touches[0].pageX; + y = ev.touches[0].pageY; + break; + case "touchend" : + break; + } + }, + onProgressTouchmove = function (ev) { + // lock the section change event listener + ev.stopPropagation(); + }, + toTimeString = function (value) { + return Math.floor(value / 60) + ":" + + ((value % 60 < 10) ? ("0" + value % 60) : value % 60); + }, + onProgressInput = function () { + progressHandler.setAttribute("data-value", toTimeString(this.value)); + }; + + tau.event.on(touchpad, ["click", "touchstart", "touchmove", "touchend"], ontouch); + tau.event.on(mediaProgress, ["touchmove"], onProgressTouchmove); + tau.event.on(mediaProgress, ["input"], onProgressInput); + + // update slider labels + labelMin.innerText = toTimeString(mediaProgress.min); + labelMax.innerText = toTimeString(mediaProgress.max); + progressHandler.setAttribute("data-value", toTimeString(mediaProgress.value)); + }; + + function onPageHide() { + websocket.close(); + if (volup) volup.removeEventListener("click"); + if (voldown) voldown.removeEventListener("click"); + if (channelup) channelup.removeEventListener("click"); + if (channeldown) channeldown.removeEventListener("click"); + if (up) up.removeEventListener("click"); + if (down) down.removeEventListener("click"); + if (right) right.removeEventListener("click"); + if (left) left.removeEventListener("click"); + if (enter) enter.removeEventListener("click"); + if (backward) backward.removeEventListener("click"); + if (home) home.removeEventListener("click"); + if (touchpad) { + touchpad.removeEventListener("click"); + touchpad.removeEventListener("touchstart"); + touchpad.removeEventListener("touchmove"); + touchpad.removeEventListener("touchend"); + } + }; + + page.addEventListener("pagebeforeshow", onPageShow); + page.addEventListener("pagebeforehide", onPageHide); +}()); \ No newline at end of file diff --git a/d2d_app/client/js/invited.js b/d2d_app/client/js/invited.js new file mode 100755 index 00000000..a0130edc --- /dev/null +++ b/d2d_app/client/js/invited.js @@ -0,0 +1,131 @@ +"use strict"; +import Actions from './actions.js'; + +const serverPort = 9000; +const serverURL = window.location.protocol + '//' + window.location.hostname; +const actions = new Actions(); +const NEW_WINDOW_TIMEOUT = 1000; +const myappsmodule = {}; + +(function () { + var xhr; + function emptyElement(elm) { + while (elm.firstChild) { + elm.removeChild(elm.firstChild); + } + return elm; + } + /** + * Open app in new window + * @param {Object} response + * @private + */ + function openAppWindow(response) { + document.getElementById("page-invited").style.display = "none"; + var timer = setTimeout(function () { + clearTimeout(timer); + document.getElementById("page-invited").style.display = "block"; + window.open(serverURL + ':' + response.port + '/app', 'newWindow'); + }, NEW_WINDOW_TIMEOUT); + }; + + function showListView(dataArray) { + var formResult = document.getElementById("d2dApps"), + imgResult = document.getElementById("d2dAppList"), + formObj, + imgObj, + textObj, + objTable, + objRow, + i, + d2dApp, + icon; + + emptyElement(imgResult); + + objTable = document.createElement("div"); + objTable.className = "result-table"; + + if (dataArray.length > 0) { + for (i = 0; i < dataArray.length; i++) { + if (dataArray[i]['d2dApp'].appName === 'Watch Together') { + formObj = document.createElement("div"); + imgObj = document.createElement("img"); + textObj = document.createElement("p"); + formObj.style.textAlign = "center"; + d2dApp = dataArray[i]['d2dApp']; + if (d2dApp.hasOwnProperty("appName")) { + if (d2dApp.iconPath) { + icon = d2dApp.iconPath.substring(d2dApp.iconPath.indexOf('/', 10) + 1); + imgObj.src = `/d2dIcon/${icon}`; + } else { + imgObj.src = `./images/icon.png`; + } + imgObj.className = "app-icon-big-img"; + imgObj.alt = d2dApp.appName; + textObj.style.display = "block"; + textObj.style.marginBottom = "60px"; + textObj.style.fontSize = "16px"; + textObj.innerHTML = d2dApp.appName; + } + imgObj.addEventListener("click", actions.launchAppOnTV( + d2dApp.appPkgID, + d2dApp.appAppID, + function (response) { + openAppWindow(response); + })); + formObj.appendChild(imgObj); + formObj.appendChild(textObj); + + imgResult.appendChild(formObj); + } + } + formResult.appendChild(imgResult); + } else { + objRow = document.createElement("div"); + objRow.className = "result-table-error"; + objRow.appendChild(document.createTextNode("No Data")); + objTable.appendChild(objRow); + } + } + + function showList() { + xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState === xhr.DONE) { + if (xhr.status === 200 || xhr.status === 201) { + showListView(JSON.parse(xhr.responseText)); + } else { + console.error(xhr.responseText); + } + } + }; + xhr.open('GET', serverURL + ':' + serverPort + '/appList'); + xhr.send(); + } + + function init() { + var eventSource = new EventSource(serverURL + ':' + serverPort + '/updateAppList'); + eventSource.addEventListener('message', evt => { + showListView(JSON.parse(evt.data)); + }, false); + eventSource.addEventListener('open', evt => { + console.log("Connected to..."); + }, false); + eventSource.addEventListener('error', evt => { + if (evt.target.readyState == EventSource.CLOSED) { + console.log("Disconnected from..."); + } else if (evt.target.readyState == EventSource.CONNECTING) { + console.log('Connecting to...'); + } + }, false); + showList(); + } + window.onload = init; + myappsmodule.openAppWindow = openAppWindow; +}()); + +export function openAppWindow(response) { + myappsmodule.openAppWindow(response); +}; + diff --git a/d2d_app/client/js/jsencrypt.js b/d2d_app/client/js/jsencrypt.js new file mode 100644 index 00000000..de5a14f6 --- /dev/null +++ b/d2d_app/client/js/jsencrypt.js @@ -0,0 +1,5371 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.JSEncrypt = {}))); +}(this, (function (exports) { 'use strict'; + +var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; +function int2char(n) { + return BI_RM.charAt(n); +} +//#region BIT_OPERATIONS +// (public) this & a +function op_and(x, y) { + return x & y; +} +// (public) this | a +function op_or(x, y) { + return x | y; +} +// (public) this ^ a +function op_xor(x, y) { + return x ^ y; +} +// (public) this & ~a +function op_andnot(x, y) { + return x & ~y; +} +// return index of lowest 1-bit in x, x < 2^31 +function lbit(x) { + if (x == 0) { + return -1; + } + var r = 0; + if ((x & 0xffff) == 0) { + x >>= 16; + r += 16; + } + if ((x & 0xff) == 0) { + x >>= 8; + r += 8; + } + if ((x & 0xf) == 0) { + x >>= 4; + r += 4; + } + if ((x & 3) == 0) { + x >>= 2; + r += 2; + } + if ((x & 1) == 0) { + ++r; + } + return r; +} +// return number of 1 bits in x +function cbit(x) { + var r = 0; + while (x != 0) { + x &= x - 1; + ++r; + } + return r; +} +//#endregion BIT_OPERATIONS + +var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var b64pad = "="; +function hex2b64(h) { + var i; + var c; + var ret = ""; + for (i = 0; i + 3 <= h.length; i += 3) { + c = parseInt(h.substring(i, i + 3), 16); + ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); + } + if (i + 1 == h.length) { + c = parseInt(h.substring(i, i + 1), 16); + ret += b64map.charAt(c << 2); + } + else if (i + 2 == h.length) { + c = parseInt(h.substring(i, i + 2), 16); + ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); + } + while ((ret.length & 3) > 0) { + ret += b64pad; + } + return ret; +} +// convert a base64 string to hex +function b64tohex(s) { + var ret = ""; + var i; + var k = 0; // b64 state, 0-3 + var slop = 0; + for (i = 0; i < s.length; ++i) { + if (s.charAt(i) == b64pad) { + break; + } + var v = b64map.indexOf(s.charAt(i)); + if (v < 0) { + continue; + } + if (k == 0) { + ret += int2char(v >> 2); + slop = v & 3; + k = 1; + } + else if (k == 1) { + ret += int2char((slop << 2) | (v >> 4)); + slop = v & 0xf; + k = 2; + } + else if (k == 2) { + ret += int2char(slop); + ret += int2char(v >> 2); + slop = v & 3; + k = 3; + } + else { + ret += int2char((slop << 2) | (v >> 4)); + ret += int2char(v & 0xf); + k = 0; + } + } + if (k == 1) { + ret += int2char(slop << 2); + } + return ret; +} + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +// Hex JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +var decoder; +var Hex = { + decode: function (a) { + var i; + if (decoder === undefined) { + var hex = "0123456789ABCDEF"; + var ignore = " \f\n\r\t\u00A0\u2028\u2029"; + decoder = {}; + for (i = 0; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + hex = hex.toLowerCase(); + for (i = 10; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + for (i = 0; i < ignore.length; ++i) { + decoder[ignore.charAt(i)] = -1; + } + } + var out = []; + var bits = 0; + var char_count = 0; + for (i = 0; i < a.length; ++i) { + var c = a.charAt(i); + if (c == "=") { + break; + } + c = decoder[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c; + if (++char_count >= 2) { + out[out.length] = bits; + bits = 0; + char_count = 0; + } + else { + bits <<= 4; + } + } + if (char_count) { + throw new Error("Hex encoding incomplete: 4 bits missing"); + } + return out; + } +}; + +// Base64 JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +var decoder$1; +var Base64 = { + decode: function (a) { + var i; + if (decoder$1 === undefined) { + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var ignore = "= \f\n\r\t\u00A0\u2028\u2029"; + decoder$1 = Object.create(null); + for (i = 0; i < 64; ++i) { + decoder$1[b64.charAt(i)] = i; + } + for (i = 0; i < ignore.length; ++i) { + decoder$1[ignore.charAt(i)] = -1; + } + } + var out = []; + var bits = 0; + var char_count = 0; + for (i = 0; i < a.length; ++i) { + var c = a.charAt(i); + if (c == "=") { + break; + } + c = decoder$1[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c; + if (++char_count >= 4) { + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + out[out.length] = bits & 0xFF; + bits = 0; + char_count = 0; + } + else { + bits <<= 6; + } + } + switch (char_count) { + case 1: + throw new Error("Base64 encoding incomplete: at least 2 bits missing"); + case 2: + out[out.length] = (bits >> 10); + break; + case 3: + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + break; + } + return out; + }, + re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/, + unarmor: function (a) { + var m = Base64.re.exec(a); + if (m) { + if (m[1]) { + a = m[1]; + } + else if (m[2]) { + a = m[2]; + } + else { + throw new Error("RegExp out of sync"); + } + } + return Base64.decode(a); + } +}; + +// Big integer base-10 printing library +// Copyright (c) 2014 Lapo Luchini +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +var max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256 +var Int10 = /** @class */ (function () { + function Int10(value) { + this.buf = [+value || 0]; + } + Int10.prototype.mulAdd = function (m, c) { + // assert(m <= 256) + var b = this.buf; + var l = b.length; + var i; + var t; + for (i = 0; i < l; ++i) { + t = b[i] * m + c; + if (t < max) { + c = 0; + } + else { + c = 0 | (t / max); + t -= c * max; + } + b[i] = t; + } + if (c > 0) { + b[i] = c; + } + }; + Int10.prototype.sub = function (c) { + // assert(m <= 256) + var b = this.buf; + var l = b.length; + var i; + var t; + for (i = 0; i < l; ++i) { + t = b[i] - c; + if (t < 0) { + t += max; + c = 1; + } + else { + c = 0; + } + b[i] = t; + } + while (b[b.length - 1] === 0) { + b.pop(); + } + }; + Int10.prototype.toString = function (base) { + if ((base || 10) != 10) { + throw new Error("only base 10 is supported"); + } + var b = this.buf; + var s = b[b.length - 1].toString(); + for (var i = b.length - 2; i >= 0; --i) { + s += (max + b[i]).toString().substring(1); + } + return s; + }; + Int10.prototype.valueOf = function () { + var b = this.buf; + var v = 0; + for (var i = b.length - 1; i >= 0; --i) { + v = v * max + b[i]; + } + return v; + }; + Int10.prototype.simplify = function () { + var b = this.buf; + return (b.length == 1) ? b[0] : this; + }; + return Int10; +}()); + +// ASN.1 JavaScript decoder +var ellipsis = "\u2026"; +var reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; +var reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; +function stringCut(str, len) { + if (str.length > len) { + str = str.substring(0, len) + ellipsis; + } + return str; +} +var Stream = /** @class */ (function () { + function Stream(enc, pos) { + this.hexDigits = "0123456789ABCDEF"; + if (enc instanceof Stream) { + this.enc = enc.enc; + this.pos = enc.pos; + } + else { + // enc should be an array or a binary string + this.enc = enc; + this.pos = pos; + } + } + Stream.prototype.get = function (pos) { + if (pos === undefined) { + pos = this.pos++; + } + if (pos >= this.enc.length) { + throw new Error("Requesting byte offset " + pos + " on a stream of length " + this.enc.length); + } + return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos]; + }; + Stream.prototype.hexByte = function (b) { + return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF); + }; + Stream.prototype.hexDump = function (start, end, raw) { + var s = ""; + for (var i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + if (raw !== true) { + switch (i & 0xF) { + case 0x7: + s += " "; + break; + case 0xF: + s += "\n"; + break; + default: + s += " "; + } + } + } + return s; + }; + Stream.prototype.isASCII = function (start, end) { + for (var i = start; i < end; ++i) { + var c = this.get(i); + if (c < 32 || c > 176) { + return false; + } + } + return true; + }; + Stream.prototype.parseStringISO = function (start, end) { + var s = ""; + for (var i = start; i < end; ++i) { + s += String.fromCharCode(this.get(i)); + } + return s; + }; + Stream.prototype.parseStringUTF = function (start, end) { + var s = ""; + for (var i = start; i < end;) { + var c = this.get(i++); + if (c < 128) { + s += String.fromCharCode(c); + } + else if ((c > 191) && (c < 224)) { + s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F)); + } + else { + s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F)); + } + } + return s; + }; + Stream.prototype.parseStringBMP = function (start, end) { + var str = ""; + var hi; + var lo; + for (var i = start; i < end;) { + hi = this.get(i++); + lo = this.get(i++); + str += String.fromCharCode((hi << 8) | lo); + } + return str; + }; + Stream.prototype.parseTime = function (start, end, shortYear) { + var s = this.parseStringISO(start, end); + var m = (shortYear ? reTimeS : reTimeL).exec(s); + if (!m) { + return "Unrecognized time: " + s; + } + if (shortYear) { + // to avoid querying the timer, use the fixed range [1970, 2069] + // it will conform with ITU X.400 [-10, +40] sliding window until 2030 + m[1] = +m[1]; + m[1] += (+m[1] < 70) ? 2000 : 1900; + } + s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4]; + if (m[5]) { + s += ":" + m[5]; + if (m[6]) { + s += ":" + m[6]; + if (m[7]) { + s += "." + m[7]; + } + } + } + if (m[8]) { + s += " UTC"; + if (m[8] != "Z") { + s += m[8]; + if (m[9]) { + s += ":" + m[9]; + } + } + } + return s; + }; + Stream.prototype.parseInteger = function (start, end) { + var v = this.get(start); + var neg = (v > 127); + var pad = neg ? 255 : 0; + var len; + var s = ""; + // skip unuseful bits (not allowed in DER) + while (v == pad && ++start < end) { + v = this.get(start); + } + len = end - start; + if (len === 0) { + return neg ? -1 : 0; + } + // show bit length of huge integers + if (len > 4) { + s = v; + len <<= 3; + while (((+s ^ pad) & 0x80) == 0) { + s = +s << 1; + --len; + } + s = "(" + len + " bit)\n"; + } + // decode the integer + if (neg) { + v = v - 256; + } + var n = new Int10(v); + for (var i = start + 1; i < end; ++i) { + n.mulAdd(256, this.get(i)); + } + return s + n.toString(); + }; + Stream.prototype.parseBitString = function (start, end, maxLength) { + var unusedBit = this.get(start); + var lenBit = ((end - start - 1) << 3) - unusedBit; + var intro = "(" + lenBit + " bit)\n"; + var s = ""; + for (var i = start + 1; i < end; ++i) { + var b = this.get(i); + var skip = (i == end - 1) ? unusedBit : 0; + for (var j = 7; j >= skip; --j) { + s += (b >> j) & 1 ? "1" : "0"; + } + if (s.length > maxLength) { + return intro + stringCut(s, maxLength); + } + } + return intro + s; + }; + Stream.prototype.parseOctetString = function (start, end, maxLength) { + if (this.isASCII(start, end)) { + return stringCut(this.parseStringISO(start, end), maxLength); + } + var len = end - start; + var s = "(" + len + " byte)\n"; + maxLength /= 2; // we work in bytes + if (len > maxLength) { + end = start + maxLength; + } + for (var i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + } + if (len > maxLength) { + s += ellipsis; + } + return s; + }; + Stream.prototype.parseOID = function (start, end, maxLength) { + var s = ""; + var n = new Int10(); + var bits = 0; + for (var i = start; i < end; ++i) { + var v = this.get(i); + n.mulAdd(128, v & 0x7F); + bits += 7; + if (!(v & 0x80)) { // finished + if (s === "") { + n = n.simplify(); + if (n instanceof Int10) { + n.sub(80); + s = "2." + n.toString(); + } + else { + var m = n < 80 ? n < 40 ? 0 : 1 : 2; + s = m + "." + (n - m * 40); + } + } + else { + s += "." + n.toString(); + } + if (s.length > maxLength) { + return stringCut(s, maxLength); + } + n = new Int10(); + bits = 0; + } + } + if (bits > 0) { + s += ".incomplete"; + } + return s; + }; + return Stream; +}()); +var ASN1 = /** @class */ (function () { + function ASN1(stream, header, length, tag, sub) { + if (!(tag instanceof ASN1Tag)) { + throw new Error("Invalid tag value."); + } + this.stream = stream; + this.header = header; + this.length = length; + this.tag = tag; + this.sub = sub; + } + ASN1.prototype.typeName = function () { + switch (this.tag.tagClass) { + case 0: // universal + switch (this.tag.tagNumber) { + case 0x00: + return "EOC"; + case 0x01: + return "BOOLEAN"; + case 0x02: + return "INTEGER"; + case 0x03: + return "BIT_STRING"; + case 0x04: + return "OCTET_STRING"; + case 0x05: + return "NULL"; + case 0x06: + return "OBJECT_IDENTIFIER"; + case 0x07: + return "ObjectDescriptor"; + case 0x08: + return "EXTERNAL"; + case 0x09: + return "REAL"; + case 0x0A: + return "ENUMERATED"; + case 0x0B: + return "EMBEDDED_PDV"; + case 0x0C: + return "UTF8String"; + case 0x10: + return "SEQUENCE"; + case 0x11: + return "SET"; + case 0x12: + return "NumericString"; + case 0x13: + return "PrintableString"; // ASCII subset + case 0x14: + return "TeletexString"; // aka T61String + case 0x15: + return "VideotexString"; + case 0x16: + return "IA5String"; // ASCII + case 0x17: + return "UTCTime"; + case 0x18: + return "GeneralizedTime"; + case 0x19: + return "GraphicString"; + case 0x1A: + return "VisibleString"; // ASCII subset + case 0x1B: + return "GeneralString"; + case 0x1C: + return "UniversalString"; + case 0x1E: + return "BMPString"; + } + return "Universal_" + this.tag.tagNumber.toString(); + case 1: + return "Application_" + this.tag.tagNumber.toString(); + case 2: + return "[" + this.tag.tagNumber.toString() + "]"; // Context + case 3: + return "Private_" + this.tag.tagNumber.toString(); + } + }; + ASN1.prototype.content = function (maxLength) { + if (this.tag === undefined) { + return null; + } + if (maxLength === undefined) { + maxLength = Infinity; + } + var content = this.posContent(); + var len = Math.abs(this.length); + if (!this.tag.isUniversal()) { + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } + return this.stream.parseOctetString(content, content + len, maxLength); + } + switch (this.tag.tagNumber) { + case 0x01: // BOOLEAN + return (this.stream.get(content) === 0) ? "false" : "true"; + case 0x02: // INTEGER + return this.stream.parseInteger(content, content + len); + case 0x03: // BIT_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseBitString(content, content + len, maxLength); + case 0x04: // OCTET_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseOctetString(content, content + len, maxLength); + // case 0x05: // NULL + case 0x06: // OBJECT_IDENTIFIER + return this.stream.parseOID(content, content + len, maxLength); + // case 0x07: // ObjectDescriptor + // case 0x08: // EXTERNAL + // case 0x09: // REAL + // case 0x0A: // ENUMERATED + // case 0x0B: // EMBEDDED_PDV + case 0x10: // SEQUENCE + case 0x11: // SET + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } + else { + return "(no elem)"; + } + case 0x0C: // UTF8String + return stringCut(this.stream.parseStringUTF(content, content + len), maxLength); + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + // case 0x19: // GraphicString + case 0x1A: // VisibleString + // case 0x1B: // GeneralString + // case 0x1C: // UniversalString + return stringCut(this.stream.parseStringISO(content, content + len), maxLength); + case 0x1E: // BMPString + return stringCut(this.stream.parseStringBMP(content, content + len), maxLength); + case 0x17: // UTCTime + case 0x18: // GeneralizedTime + return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17)); + } + return null; + }; + ASN1.prototype.toString = function () { + return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]"; + }; + ASN1.prototype.toPrettyString = function (indent) { + if (indent === undefined) { + indent = ""; + } + var s = indent + this.typeName() + " @" + this.stream.pos; + if (this.length >= 0) { + s += "+"; + } + s += this.length; + if (this.tag.tagConstructed) { + s += " (constructed)"; + } + else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) { + s += " (encapsulates)"; + } + s += "\n"; + if (this.sub !== null) { + indent += " "; + for (var i = 0, max = this.sub.length; i < max; ++i) { + s += this.sub[i].toPrettyString(indent); + } + } + return s; + }; + ASN1.prototype.posStart = function () { + return this.stream.pos; + }; + ASN1.prototype.posContent = function () { + return this.stream.pos + this.header; + }; + ASN1.prototype.posEnd = function () { + return this.stream.pos + this.header + Math.abs(this.length); + }; + ASN1.prototype.toHexString = function () { + return this.stream.hexDump(this.posStart(), this.posEnd(), true); + }; + ASN1.decodeLength = function (stream) { + var buf = stream.get(); + var len = buf & 0x7F; + if (len == buf) { + return len; + } + // no reason to use Int10, as it would be a huge buffer anyways + if (len > 6) { + throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1)); + } + if (len === 0) { + return null; + } // undefined + buf = 0; + for (var i = 0; i < len; ++i) { + buf = (buf * 256) + stream.get(); + } + return buf; + }; + /** + * Retrieve the hexadecimal value (as a string) of the current ASN.1 element + * @returns {string} + * @public + */ + ASN1.prototype.getHexStringValue = function () { + var hexString = this.toHexString(); + var offset = this.header * 2; + var length = this.length * 2; + return hexString.substr(offset, length); + }; + ASN1.decode = function (str) { + var stream; + if (!(str instanceof Stream)) { + stream = new Stream(str, 0); + } + else { + stream = str; + } + var streamStart = new Stream(stream); + var tag = new ASN1Tag(stream); + var len = ASN1.decodeLength(stream); + var start = stream.pos; + var header = start - streamStart.pos; + var sub = null; + var getSub = function () { + var ret = []; + if (len !== null) { + // definite length + var end = start + len; + while (stream.pos < end) { + ret[ret.length] = ASN1.decode(stream); + } + if (stream.pos != end) { + throw new Error("Content size is not correct for container starting at offset " + start); + } + } + else { + // undefined length + try { + for (;;) { + var s = ASN1.decode(stream); + if (s.tag.isEOC()) { + break; + } + ret[ret.length] = s; + } + len = start - stream.pos; // undefined lengths are represented as negative values + } + catch (e) { + throw new Error("Exception while decoding undefined length content: " + e); + } + } + return ret; + }; + if (tag.tagConstructed) { + // must have valid content + sub = getSub(); + } + else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) { + // sometimes BitString and OctetString are used to encapsulate ASN.1 + try { + if (tag.tagNumber == 0x03) { + if (stream.get() != 0) { + throw new Error("BIT STRINGs with unused bits cannot encapsulate."); + } + } + sub = getSub(); + for (var i = 0; i < sub.length; ++i) { + if (sub[i].tag.isEOC()) { + throw new Error("EOC is not supposed to be actual content."); + } + } + } + catch (e) { + // but silently ignore when they don't + sub = null; + } + } + if (sub === null) { + if (len === null) { + throw new Error("We can't skip over an invalid tag with undefined length at offset " + start); + } + stream.pos = start + Math.abs(len); + } + return new ASN1(streamStart, header, len, tag, sub); + }; + return ASN1; +}()); +var ASN1Tag = /** @class */ (function () { + function ASN1Tag(stream) { + var buf = stream.get(); + this.tagClass = buf >> 6; + this.tagConstructed = ((buf & 0x20) !== 0); + this.tagNumber = buf & 0x1F; + if (this.tagNumber == 0x1F) { // long tag + var n = new Int10(); + do { + buf = stream.get(); + n.mulAdd(128, buf & 0x7F); + } while (buf & 0x80); + this.tagNumber = n.simplify(); + } + } + ASN1Tag.prototype.isUniversal = function () { + return this.tagClass === 0x00; + }; + ASN1Tag.prototype.isEOC = function () { + return this.tagClass === 0x00 && this.tagNumber === 0x00; + }; + return ASN1Tag; +}()); + +// Copyright (c) 2005 Tom Wu +// Bits per digit +var dbits; +// JavaScript engine analysis +var canary = 0xdeadbeefcafe; +var j_lm = ((canary & 0xffffff) == 0xefcafe); +//#region +var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]; +var lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; +//#endregion +// (public) Constructor +var BigInteger = /** @class */ (function () { + function BigInteger(a, b, c) { + if (a != null) { + if ("number" == typeof a) { + this.fromNumber(a, b, c); + } + else if (b == null && "string" != typeof a) { + this.fromString(a, 256); + } + else { + this.fromString(a, b); + } + } + } + //#region PUBLIC + // BigInteger.prototype.toString = bnToString; + // (public) return string representation in given radix + BigInteger.prototype.toString = function (b) { + if (this.s < 0) { + return "-" + this.negate().toString(b); + } + var k; + if (b == 16) { + k = 4; + } + else if (b == 8) { + k = 3; + } + else if (b == 2) { + k = 1; + } + else if (b == 32) { + k = 5; + } + else if (b == 4) { + k = 2; + } + else { + return this.toRadix(b); + } + var km = (1 << k) - 1; + var d; + var m = false; + var r = ""; + var i = this.t; + var p = this.DB - (i * this.DB) % k; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) > 0) { + m = true; + r = int2char(d); + } + while (i >= 0) { + if (p < k) { + d = (this[i] & ((1 << p) - 1)) << (k - p); + d |= this[--i] >> (p += this.DB - k); + } + else { + d = (this[i] >> (p -= k)) & km; + if (p <= 0) { + p += this.DB; + --i; + } + } + if (d > 0) { + m = true; + } + if (m) { + r += int2char(d); + } + } + } + return m ? r : "0"; + }; + // BigInteger.prototype.negate = bnNegate; + // (public) -this + BigInteger.prototype.negate = function () { + var r = nbi(); + BigInteger.ZERO.subTo(this, r); + return r; + }; + // BigInteger.prototype.abs = bnAbs; + // (public) |this| + BigInteger.prototype.abs = function () { + return (this.s < 0) ? this.negate() : this; + }; + // BigInteger.prototype.compareTo = bnCompareTo; + // (public) return + if this > a, - if this < a, 0 if equal + BigInteger.prototype.compareTo = function (a) { + var r = this.s - a.s; + if (r != 0) { + return r; + } + var i = this.t; + r = i - a.t; + if (r != 0) { + return (this.s < 0) ? -r : r; + } + while (--i >= 0) { + if ((r = this[i] - a[i]) != 0) { + return r; + } + } + return 0; + }; + // BigInteger.prototype.bitLength = bnBitLength; + // (public) return the number of bits in "this" + BigInteger.prototype.bitLength = function () { + if (this.t <= 0) { + return 0; + } + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)); + }; + // BigInteger.prototype.mod = bnMod; + // (public) this mod a + BigInteger.prototype.mod = function (a) { + var r = nbi(); + this.abs().divRemTo(a, null, r); + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + a.subTo(r, r); + } + return r; + }; + // BigInteger.prototype.modPowInt = bnModPowInt; + // (public) this^e % m, 0 <= e < 2^32 + BigInteger.prototype.modPowInt = function (e, m) { + var z; + if (e < 256 || m.isEven()) { + z = new Classic(m); + } + else { + z = new Montgomery(m); + } + return this.exp(e, z); + }; + // BigInteger.prototype.clone = bnClone; + // (public) + BigInteger.prototype.clone = function () { + var r = nbi(); + this.copyTo(r); + return r; + }; + // BigInteger.prototype.intValue = bnIntValue; + // (public) return value as integer + BigInteger.prototype.intValue = function () { + if (this.s < 0) { + if (this.t == 1) { + return this[0] - this.DV; + } + else if (this.t == 0) { + return -1; + } + } + else if (this.t == 1) { + return this[0]; + } + else if (this.t == 0) { + return 0; + } + // assumes 16 < DB < 32 + return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]; + }; + // BigInteger.prototype.byteValue = bnByteValue; + // (public) return value as byte + BigInteger.prototype.byteValue = function () { + return (this.t == 0) ? this.s : (this[0] << 24) >> 24; + }; + // BigInteger.prototype.shortValue = bnShortValue; + // (public) return value as short (assumes DB>=16) + BigInteger.prototype.shortValue = function () { + return (this.t == 0) ? this.s : (this[0] << 16) >> 16; + }; + // BigInteger.prototype.signum = bnSigNum; + // (public) 0 if this == 0, 1 if this > 0 + BigInteger.prototype.signum = function () { + if (this.s < 0) { + return -1; + } + else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) { + return 0; + } + else { + return 1; + } + }; + // BigInteger.prototype.toByteArray = bnToByteArray; + // (public) convert to bigendian byte array + BigInteger.prototype.toByteArray = function () { + var i = this.t; + var r = []; + r[0] = this.s; + var p = this.DB - (i * this.DB) % 8; + var d; + var k = 0; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) { + r[k++] = d | (this.s << (this.DB - p)); + } + while (i >= 0) { + if (p < 8) { + d = (this[i] & ((1 << p) - 1)) << (8 - p); + d |= this[--i] >> (p += this.DB - 8); + } + else { + d = (this[i] >> (p -= 8)) & 0xff; + if (p <= 0) { + p += this.DB; + --i; + } + } + if ((d & 0x80) != 0) { + d |= -256; + } + if (k == 0 && (this.s & 0x80) != (d & 0x80)) { + ++k; + } + if (k > 0 || d != this.s) { + r[k++] = d; + } + } + } + return r; + }; + // BigInteger.prototype.equals = bnEquals; + BigInteger.prototype.equals = function (a) { + return (this.compareTo(a) == 0); + }; + // BigInteger.prototype.min = bnMin; + BigInteger.prototype.min = function (a) { + return (this.compareTo(a) < 0) ? this : a; + }; + // BigInteger.prototype.max = bnMax; + BigInteger.prototype.max = function (a) { + return (this.compareTo(a) > 0) ? this : a; + }; + // BigInteger.prototype.and = bnAnd; + BigInteger.prototype.and = function (a) { + var r = nbi(); + this.bitwiseTo(a, op_and, r); + return r; + }; + // BigInteger.prototype.or = bnOr; + BigInteger.prototype.or = function (a) { + var r = nbi(); + this.bitwiseTo(a, op_or, r); + return r; + }; + // BigInteger.prototype.xor = bnXor; + BigInteger.prototype.xor = function (a) { + var r = nbi(); + this.bitwiseTo(a, op_xor, r); + return r; + }; + // BigInteger.prototype.andNot = bnAndNot; + BigInteger.prototype.andNot = function (a) { + var r = nbi(); + this.bitwiseTo(a, op_andnot, r); + return r; + }; + // BigInteger.prototype.not = bnNot; + // (public) ~this + BigInteger.prototype.not = function () { + var r = nbi(); + for (var i = 0; i < this.t; ++i) { + r[i] = this.DM & ~this[i]; + } + r.t = this.t; + r.s = ~this.s; + return r; + }; + // BigInteger.prototype.shiftLeft = bnShiftLeft; + // (public) this << n + BigInteger.prototype.shiftLeft = function (n) { + var r = nbi(); + if (n < 0) { + this.rShiftTo(-n, r); + } + else { + this.lShiftTo(n, r); + } + return r; + }; + // BigInteger.prototype.shiftRight = bnShiftRight; + // (public) this >> n + BigInteger.prototype.shiftRight = function (n) { + var r = nbi(); + if (n < 0) { + this.lShiftTo(-n, r); + } + else { + this.rShiftTo(n, r); + } + return r; + }; + // BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; + // (public) returns index of lowest 1-bit (or -1 if none) + BigInteger.prototype.getLowestSetBit = function () { + for (var i = 0; i < this.t; ++i) { + if (this[i] != 0) { + return i * this.DB + lbit(this[i]); + } + } + if (this.s < 0) { + return this.t * this.DB; + } + return -1; + }; + // BigInteger.prototype.bitCount = bnBitCount; + // (public) return number of set bits + BigInteger.prototype.bitCount = function () { + var r = 0; + var x = this.s & this.DM; + for (var i = 0; i < this.t; ++i) { + r += cbit(this[i] ^ x); + } + return r; + }; + // BigInteger.prototype.testBit = bnTestBit; + // (public) true iff nth bit is set + BigInteger.prototype.testBit = function (n) { + var j = Math.floor(n / this.DB); + if (j >= this.t) { + return (this.s != 0); + } + return ((this[j] & (1 << (n % this.DB))) != 0); + }; + // BigInteger.prototype.setBit = bnSetBit; + // (public) this | (1< 1) { + var g2 = nbi(); + z.sqrTo(g[1], g2); + while (n <= km) { + g[n] = nbi(); + z.mulTo(g2, g[n - 2], g[n]); + n += 2; + } + } + var j = e.t - 1; + var w; + var is1 = true; + var r2 = nbi(); + var t; + i = nbits(e[j]) - 1; + while (j >= 0) { + if (i >= k1) { + w = (e[j] >> (i - k1)) & km; + } + else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); + if (j > 0) { + w |= e[j - 1] >> (this.DB + i - k1); + } + } + n = k; + while ((w & 1) == 0) { + w >>= 1; + --n; + } + if ((i -= n) < 0) { + i += this.DB; + --j; + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } + else { + while (n > 1) { + z.sqrTo(r, r2); + z.sqrTo(r2, r); + n -= 2; + } + if (n > 0) { + z.sqrTo(r, r2); + } + else { + t = r; + r = r2; + r2 = t; + } + z.mulTo(r2, g[w], r); + } + while (j >= 0 && (e[j] & (1 << i)) == 0) { + z.sqrTo(r, r2); + t = r; + r = r2; + r2 = t; + if (--i < 0) { + i = this.DB - 1; + --j; + } + } + } + return z.revert(r); + }; + // BigInteger.prototype.modInverse = bnModInverse; + // (public) 1/this % m (HAC 14.61) + BigInteger.prototype.modInverse = function (m) { + var ac = m.isEven(); + if ((this.isEven() && ac) || m.signum() == 0) { + return BigInteger.ZERO; + } + var u = m.clone(); + var v = this.clone(); + var a = nbv(1); + var b = nbv(0); + var c = nbv(0); + var d = nbv(1); + while (u.signum() != 0) { + while (u.isEven()) { + u.rShiftTo(1, u); + if (ac) { + if (!a.isEven() || !b.isEven()) { + a.addTo(this, a); + b.subTo(m, b); + } + a.rShiftTo(1, a); + } + else if (!b.isEven()) { + b.subTo(m, b); + } + b.rShiftTo(1, b); + } + while (v.isEven()) { + v.rShiftTo(1, v); + if (ac) { + if (!c.isEven() || !d.isEven()) { + c.addTo(this, c); + d.subTo(m, d); + } + c.rShiftTo(1, c); + } + else if (!d.isEven()) { + d.subTo(m, d); + } + d.rShiftTo(1, d); + } + if (u.compareTo(v) >= 0) { + u.subTo(v, u); + if (ac) { + a.subTo(c, a); + } + b.subTo(d, b); + } + else { + v.subTo(u, v); + if (ac) { + c.subTo(a, c); + } + d.subTo(b, d); + } + } + if (v.compareTo(BigInteger.ONE) != 0) { + return BigInteger.ZERO; + } + if (d.compareTo(m) >= 0) { + return d.subtract(m); + } + if (d.signum() < 0) { + d.addTo(m, d); + } + else { + return d; + } + if (d.signum() < 0) { + return d.add(m); + } + else { + return d; + } + }; + // BigInteger.prototype.pow = bnPow; + // (public) this^e + BigInteger.prototype.pow = function (e) { + return this.exp(e, new NullExp()); + }; + // BigInteger.prototype.gcd = bnGCD; + // (public) gcd(this,a) (HAC 14.54) + BigInteger.prototype.gcd = function (a) { + var x = (this.s < 0) ? this.negate() : this.clone(); + var y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + var t = x; + x = y; + y = t; + } + var i = x.getLowestSetBit(); + var g = y.getLowestSetBit(); + if (g < 0) { + return x; + } + if (i < g) { + g = i; + } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + while (x.signum() > 0) { + if ((i = x.getLowestSetBit()) > 0) { + x.rShiftTo(i, x); + } + if ((i = y.getLowestSetBit()) > 0) { + y.rShiftTo(i, y); + } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } + else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + } + if (g > 0) { + y.lShiftTo(g, y); + } + return y; + }; + // BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + // (public) test primality with certainty >= 1-.5^t + BigInteger.prototype.isProbablePrime = function (t) { + var i; + var x = this.abs(); + if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) { + for (i = 0; i < lowprimes.length; ++i) { + if (x[0] == lowprimes[i]) { + return true; + } + } + return false; + } + if (x.isEven()) { + return false; + } + i = 1; + while (i < lowprimes.length) { + var m = lowprimes[i]; + var j = i + 1; + while (j < lowprimes.length && m < lplim) { + m *= lowprimes[j++]; + } + m = x.modInt(m); + while (i < j) { + if (m % lowprimes[i++] == 0) { + return false; + } + } + } + return x.millerRabin(t); + }; + //#endregion PUBLIC + //#region PROTECTED + // BigInteger.prototype.copyTo = bnpCopyTo; + // (protected) copy this to r + BigInteger.prototype.copyTo = function (r) { + for (var i = this.t - 1; i >= 0; --i) { + r[i] = this[i]; + } + r.t = this.t; + r.s = this.s; + }; + // BigInteger.prototype.fromInt = bnpFromInt; + // (protected) set from integer value x, -DV <= x < DV + BigInteger.prototype.fromInt = function (x) { + this.t = 1; + this.s = (x < 0) ? -1 : 0; + if (x > 0) { + this[0] = x; + } + else if (x < -1) { + this[0] = x + this.DV; + } + else { + this.t = 0; + } + }; + // BigInteger.prototype.fromString = bnpFromString; + // (protected) set from string and radix + BigInteger.prototype.fromString = function (s, b) { + var k; + if (b == 16) { + k = 4; + } + else if (b == 8) { + k = 3; + } + else if (b == 256) { + k = 8; + /* byte array */ + } + else if (b == 2) { + k = 1; + } + else if (b == 32) { + k = 5; + } + else if (b == 4) { + k = 2; + } + else { + this.fromRadix(s, b); + return; + } + this.t = 0; + this.s = 0; + var i = s.length; + var mi = false; + var sh = 0; + while (--i >= 0) { + var x = (k == 8) ? (+s[i]) & 0xff : intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-") { + mi = true; + } + continue; + } + mi = false; + if (sh == 0) { + this[this.t++] = x; + } + else if (sh + k > this.DB) { + this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh; + this[this.t++] = (x >> (this.DB - sh)); + } + else { + this[this.t - 1] |= x << sh; + } + sh += k; + if (sh >= this.DB) { + sh -= this.DB; + } + } + if (k == 8 && ((+s[0]) & 0x80) != 0) { + this.s = -1; + if (sh > 0) { + this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh; + } + } + this.clamp(); + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + }; + // BigInteger.prototype.clamp = bnpClamp; + // (protected) clamp off excess high words + BigInteger.prototype.clamp = function () { + var c = this.s & this.DM; + while (this.t > 0 && this[this.t - 1] == c) { + --this.t; + } + }; + // BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + // (protected) r = this << n*DB + BigInteger.prototype.dlShiftTo = function (n, r) { + var i; + for (i = this.t - 1; i >= 0; --i) { + r[i + n] = this[i]; + } + for (i = n - 1; i >= 0; --i) { + r[i] = 0; + } + r.t = this.t + n; + r.s = this.s; + }; + // BigInteger.prototype.drShiftTo = bnpDRShiftTo; + // (protected) r = this >> n*DB + BigInteger.prototype.drShiftTo = function (n, r) { + for (var i = n; i < this.t; ++i) { + r[i - n] = this[i]; + } + r.t = Math.max(this.t - n, 0); + r.s = this.s; + }; + // BigInteger.prototype.lShiftTo = bnpLShiftTo; + // (protected) r = this << n + BigInteger.prototype.lShiftTo = function (n, r) { + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << cbs) - 1; + var ds = Math.floor(n / this.DB); + var c = (this.s << bs) & this.DM; + for (var i = this.t - 1; i >= 0; --i) { + r[i + ds + 1] = (this[i] >> cbs) | c; + c = (this[i] & bm) << bs; + } + for (var i = ds - 1; i >= 0; --i) { + r[i] = 0; + } + r[ds] = c; + r.t = this.t + ds + 1; + r.s = this.s; + r.clamp(); + }; + // BigInteger.prototype.rShiftTo = bnpRShiftTo; + // (protected) r = this >> n + BigInteger.prototype.rShiftTo = function (n, r) { + r.s = this.s; + var ds = Math.floor(n / this.DB); + if (ds >= this.t) { + r.t = 0; + return; + } + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << bs) - 1; + r[0] = this[ds] >> bs; + for (var i = ds + 1; i < this.t; ++i) { + r[i - ds - 1] |= (this[i] & bm) << cbs; + r[i - ds] = this[i] >> bs; + } + if (bs > 0) { + r[this.t - ds - 1] |= (this.s & bm) << cbs; + } + r.t = this.t - ds; + r.clamp(); + }; + // BigInteger.prototype.subTo = bnpSubTo; + // (protected) r = this - a + BigInteger.prototype.subTo = function (a, r) { + var i = 0; + var c = 0; + var m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] - a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c -= a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) { + r[i++] = this.DV + c; + } + else if (c > 0) { + r[i++] = c; + } + r.t = i; + r.clamp(); + }; + // BigInteger.prototype.multiplyTo = bnpMultiplyTo; + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + BigInteger.prototype.multiplyTo = function (a, r) { + var x = this.abs(); + var y = a.abs(); + var i = x.t; + r.t = i + y.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < y.t; ++i) { + r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); + } + r.s = 0; + r.clamp(); + if (this.s != a.s) { + BigInteger.ZERO.subTo(r, r); + } + }; + // BigInteger.prototype.squareTo = bnpSquareTo; + // (protected) r = this^2, r != this (HAC 14.16) + BigInteger.prototype.squareTo = function (r) { + var x = this.abs(); + var i = r.t = 2 * x.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < x.t - 1; ++i) { + var c = x.am(i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) { + r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1); + } + r.s = 0; + r.clamp(); + }; + // BigInteger.prototype.divRemTo = bnpDivRemTo; + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + BigInteger.prototype.divRemTo = function (m, q, r) { + var pm = m.abs(); + if (pm.t <= 0) { + return; + } + var pt = this.abs(); + if (pt.t < pm.t) { + if (q != null) { + q.fromInt(0); + } + if (r != null) { + this.copyTo(r); + } + return; + } + if (r == null) { + r = nbi(); + } + var y = nbi(); + var ts = this.s; + var ms = m.s; + var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y); + pt.lShiftTo(nsh, r); + } + else { + pm.copyTo(y); + pt.copyTo(r); + } + var ys = y.t; + var y0 = y[ys - 1]; + if (y0 == 0) { + return; + } + var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0); + var d1 = this.FV / yt; + var d2 = (1 << this.F1) / yt; + var e = 1 << this.F2; + var i = r.t; + var j = i - ys; + var t = (q == null) ? nbi() : q; + y.dlShiftTo(j, t); + if (r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t, r); + } + BigInteger.ONE.dlShiftTo(ys, t); + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) { + y[y.t++] = 0; + } + while (--j >= 0) { + // Estimate quotient digit + var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t); + r.subTo(t, r); + while (r[i] < --qd) { + r.subTo(t, r); + } + } + } + if (q != null) { + r.drShiftTo(ys, q); + if (ts != ms) { + BigInteger.ZERO.subTo(q, q); + } + } + r.t = ys; + r.clamp(); + if (nsh > 0) { + r.rShiftTo(nsh, r); + } // Denormalize remainder + if (ts < 0) { + BigInteger.ZERO.subTo(r, r); + } + }; + // BigInteger.prototype.invDigit = bnpInvDigit; + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + BigInteger.prototype.invDigit = function () { + if (this.t < 1) { + return 0; + } + var x = this[0]; + if ((x & 1) == 0) { + return 0; + } + var y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y; + }; + // BigInteger.prototype.isEven = bnpIsEven; + // (protected) true iff this is even + BigInteger.prototype.isEven = function () { + return ((this.t > 0) ? (this[0] & 1) : this.s) == 0; + }; + // BigInteger.prototype.exp = bnpExp; + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + BigInteger.prototype.exp = function (e, z) { + if (e > 0xffffffff || e < 1) { + return BigInteger.ONE; + } + var r = nbi(); + var r2 = nbi(); + var g = z.convert(this); + var i = nbits(e) - 1; + g.copyTo(r); + while (--i >= 0) { + z.sqrTo(r, r2); + if ((e & (1 << i)) > 0) { + z.mulTo(r2, g, r); + } + else { + var t = r; + r = r2; + r2 = t; + } + } + return z.revert(r); + }; + // BigInteger.prototype.chunkSize = bnpChunkSize; + // (protected) return x s.t. r^x < DV + BigInteger.prototype.chunkSize = function (r) { + return Math.floor(Math.LN2 * this.DB / Math.log(r)); + }; + // BigInteger.prototype.toRadix = bnpToRadix; + // (protected) convert to radix string + BigInteger.prototype.toRadix = function (b) { + if (b == null) { + b = 10; + } + if (this.signum() == 0 || b < 2 || b > 36) { + return "0"; + } + var cs = this.chunkSize(b); + var a = Math.pow(b, cs); + var d = nbv(a); + var y = nbi(); + var z = nbi(); + var r = ""; + this.divRemTo(d, y, z); + while (y.signum() > 0) { + r = (a + z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d, y, z); + } + return z.intValue().toString(b) + r; + }; + // BigInteger.prototype.fromRadix = bnpFromRadix; + // (protected) convert from radix string + BigInteger.prototype.fromRadix = function (s, b) { + this.fromInt(0); + if (b == null) { + b = 10; + } + var cs = this.chunkSize(b); + var d = Math.pow(b, cs); + var mi = false; + var j = 0; + var w = 0; + for (var i = 0; i < s.length; ++i) { + var x = intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-" && this.signum() == 0) { + mi = true; + } + continue; + } + w = b * w + x; + if (++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w, 0); + j = 0; + w = 0; + } + } + if (j > 0) { + this.dMultiply(Math.pow(b, j)); + this.dAddOffset(w, 0); + } + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + }; + // BigInteger.prototype.fromNumber = bnpFromNumber; + // (protected) alternate constructor + BigInteger.prototype.fromNumber = function (a, b, c) { + if ("number" == typeof b) { + // new BigInteger(int,int,RNG) + if (a < 2) { + this.fromInt(1); + } + else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } // force odd + while (!this.isProbablePrime(b)) { + this.dAddOffset(2, 0); + if (this.bitLength() > a) { + this.subTo(BigInteger.ONE.shiftLeft(a - 1), this); + } + } + } + } + else { + // new BigInteger(int,RNG) + var x = []; + var t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { + x[0] &= ((1 << t) - 1); + } + else { + x[0] = 0; + } + this.fromString(x, 256); + } + }; + // BigInteger.prototype.bitwiseTo = bnpBitwiseTo; + // (protected) r = this op a (bitwise) + BigInteger.prototype.bitwiseTo = function (a, op, r) { + var i; + var f; + var m = Math.min(a.t, this.t); + for (i = 0; i < m; ++i) { + r[i] = op(this[i], a[i]); + } + if (a.t < this.t) { + f = a.s & this.DM; + for (i = m; i < this.t; ++i) { + r[i] = op(this[i], f); + } + r.t = this.t; + } + else { + f = this.s & this.DM; + for (i = m; i < a.t; ++i) { + r[i] = op(f, a[i]); + } + r.t = a.t; + } + r.s = op(this.s, a.s); + r.clamp(); + }; + // BigInteger.prototype.changeBit = bnpChangeBit; + // (protected) this op (1<>= this.DB; + } + if (a.t < this.t) { + c += a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while (i < a.t) { + c += a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c > 0) { + r[i++] = c; + } + else if (c < -1) { + r[i++] = this.DV + c; + } + r.t = i; + r.clamp(); + }; + // BigInteger.prototype.dMultiply = bnpDMultiply; + // (protected) this *= n, this >= 0, 1 < n < DV + BigInteger.prototype.dMultiply = function (n) { + this[this.t] = this.am(0, n - 1, this, 0, 0, this.t); + ++this.t; + this.clamp(); + }; + // BigInteger.prototype.dAddOffset = bnpDAddOffset; + // (protected) this += n << w words, this >= 0 + BigInteger.prototype.dAddOffset = function (n, w) { + if (n == 0) { + return; + } + while (this.t <= w) { + this[this.t++] = 0; + } + this[w] += n; + while (this[w] >= this.DV) { + this[w] -= this.DV; + if (++w >= this.t) { + this[this.t++] = 0; + } + ++this[w]; + } + }; + // BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; + // (protected) r = lower n words of "this * a", a.t <= n + // "this" should be the larger one if appropriate. + BigInteger.prototype.multiplyLowerTo = function (a, n, r) { + var i = Math.min(this.t + a.t, n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while (i > 0) { + r[--i] = 0; + } + for (var j = r.t - this.t; i < j; ++i) { + r[i + this.t] = this.am(0, a[i], r, i, 0, this.t); + } + for (var j = Math.min(a.t, n); i < j; ++i) { + this.am(0, a[i], r, i, 0, n - i); + } + r.clamp(); + }; + // BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; + // (protected) r = "this * a" without lower n words, n > 0 + // "this" should be the larger one if appropriate. + BigInteger.prototype.multiplyUpperTo = function (a, n, r) { + --n; + var i = r.t = this.t + a.t - n; + r.s = 0; // assumes a,this >= 0 + while (--i >= 0) { + r[i] = 0; + } + for (i = Math.max(n - this.t, 0); i < a.t; ++i) { + r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n); + } + r.clamp(); + r.drShiftTo(1, r); + }; + // BigInteger.prototype.modInt = bnpModInt; + // (protected) this % n, n < 2^26 + BigInteger.prototype.modInt = function (n) { + if (n <= 0) { + return 0; + } + var d = this.DV % n; + var r = (this.s < 0) ? n - 1 : 0; + if (this.t > 0) { + if (d == 0) { + r = this[0] % n; + } + else { + for (var i = this.t - 1; i >= 0; --i) { + r = (d * r + this[i]) % n; + } + } + } + return r; + }; + // BigInteger.prototype.millerRabin = bnpMillerRabin; + // (protected) true if probably prime (HAC 4.24, Miller-Rabin) + BigInteger.prototype.millerRabin = function (t) { + var n1 = this.subtract(BigInteger.ONE); + var k = n1.getLowestSetBit(); + if (k <= 0) { + return false; + } + var r = n1.shiftRight(k); + t = (t + 1) >> 1; + if (t > lowprimes.length) { + t = lowprimes.length; + } + var a = nbi(); + for (var i = 0; i < t; ++i) { + // Pick bases at random, instead of starting at 2 + a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]); + var y = a.modPow(r, this); + if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1; + while (j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2, this); + if (y.compareTo(BigInteger.ONE) == 0) { + return false; + } + } + if (y.compareTo(n1) != 0) { + return false; + } + } + } + return true; + }; + // BigInteger.prototype.square = bnSquare; + // (public) this^2 + BigInteger.prototype.square = function () { + var r = nbi(); + this.squareTo(r); + return r; + }; + //#region ASYNC + // Public API method + BigInteger.prototype.gcda = function (a, callback) { + var x = (this.s < 0) ? this.negate() : this.clone(); + var y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + var t = x; + x = y; + y = t; + } + var i = x.getLowestSetBit(); + var g = y.getLowestSetBit(); + if (g < 0) { + callback(x); + return; + } + if (i < g) { + g = i; + } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen. + var gcda1 = function () { + if ((i = x.getLowestSetBit()) > 0) { + x.rShiftTo(i, x); + } + if ((i = y.getLowestSetBit()) > 0) { + y.rShiftTo(i, y); + } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } + else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + if (!(x.signum() > 0)) { + if (g > 0) { + y.lShiftTo(g, y); + } + setTimeout(function () { callback(y); }, 0); // escape + } + else { + setTimeout(gcda1, 0); + } + }; + setTimeout(gcda1, 10); + }; + // (protected) alternate constructor + BigInteger.prototype.fromNumberAsync = function (a, b, c, callback) { + if ("number" == typeof b) { + if (a < 2) { + this.fromInt(1); + } + else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } + var bnp_1 = this; + var bnpfn1_1 = function () { + bnp_1.dAddOffset(2, 0); + if (bnp_1.bitLength() > a) { + bnp_1.subTo(BigInteger.ONE.shiftLeft(a - 1), bnp_1); + } + if (bnp_1.isProbablePrime(b)) { + setTimeout(function () { callback(); }, 0); // escape + } + else { + setTimeout(bnpfn1_1, 0); + } + }; + setTimeout(bnpfn1_1, 0); + } + } + else { + var x = []; + var t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { + x[0] &= ((1 << t) - 1); + } + else { + x[0] = 0; + } + this.fromString(x, 256); + } + }; + return BigInteger; +}()); +//#region REDUCERS +//#region NullExp +var NullExp = /** @class */ (function () { + function NullExp() { + } + // NullExp.prototype.convert = nNop; + NullExp.prototype.convert = function (x) { + return x; + }; + // NullExp.prototype.revert = nNop; + NullExp.prototype.revert = function (x) { + return x; + }; + // NullExp.prototype.mulTo = nMulTo; + NullExp.prototype.mulTo = function (x, y, r) { + x.multiplyTo(y, r); + }; + // NullExp.prototype.sqrTo = nSqrTo; + NullExp.prototype.sqrTo = function (x, r) { + x.squareTo(r); + }; + return NullExp; +}()); +// Modular reduction using "classic" algorithm +var Classic = /** @class */ (function () { + function Classic(m) { + this.m = m; + } + // Classic.prototype.convert = cConvert; + Classic.prototype.convert = function (x) { + if (x.s < 0 || x.compareTo(this.m) >= 0) { + return x.mod(this.m); + } + else { + return x; + } + }; + // Classic.prototype.revert = cRevert; + Classic.prototype.revert = function (x) { + return x; + }; + // Classic.prototype.reduce = cReduce; + Classic.prototype.reduce = function (x) { + x.divRemTo(this.m, null, x); + }; + // Classic.prototype.mulTo = cMulTo; + Classic.prototype.mulTo = function (x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); + }; + // Classic.prototype.sqrTo = cSqrTo; + Classic.prototype.sqrTo = function (x, r) { + x.squareTo(r); + this.reduce(r); + }; + return Classic; +}()); +//#endregion +//#region Montgomery +// Montgomery reduction +var Montgomery = /** @class */ (function () { + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (m.DB - 15)) - 1; + this.mt2 = 2 * m.t; + } + // Montgomery.prototype.convert = montConvert; + // xR mod m + Montgomery.prototype.convert = function (x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t, r); + r.divRemTo(this.m, null, r); + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + this.m.subTo(r, r); + } + return r; + }; + // Montgomery.prototype.revert = montRevert; + // x/R mod m + Montgomery.prototype.revert = function (x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + }; + // Montgomery.prototype.reduce = montReduce; + // x = x/R mod m (HAC 14.32) + Montgomery.prototype.reduce = function (x) { + while (x.t <= this.mt2) { + // pad x so am has enough room later + x[x.t++] = 0; + } + for (var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i] & 0x7fff; + var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; + // use am to combine the multiply-shift-add into one call + j = i + this.m.t; + x[j] += this.m.am(0, u0, x, i, 0, this.m.t); + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV; + x[++j]++; + } + } + x.clamp(); + x.drShiftTo(this.m.t, x); + if (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + }; + // Montgomery.prototype.mulTo = montMulTo; + // r = "xy/R mod m"; x,y != r + Montgomery.prototype.mulTo = function (x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); + }; + // Montgomery.prototype.sqrTo = montSqrTo; + // r = "x^2/R mod m"; x != r + Montgomery.prototype.sqrTo = function (x, r) { + x.squareTo(r); + this.reduce(r); + }; + return Montgomery; +}()); +//#endregion Montgomery +//#region Barrett +// Barrett modular reduction +var Barrett = /** @class */ (function () { + function Barrett(m) { + this.m = m; + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2 * m.t, this.r2); + this.mu = this.r2.divide(m); + } + // Barrett.prototype.convert = barrettConvert; + Barrett.prototype.convert = function (x) { + if (x.s < 0 || x.t > 2 * this.m.t) { + return x.mod(this.m); + } + else if (x.compareTo(this.m) < 0) { + return x; + } + else { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + }; + // Barrett.prototype.revert = barrettRevert; + Barrett.prototype.revert = function (x) { + return x; + }; + // Barrett.prototype.reduce = barrettReduce; + // x = x mod m (HAC 14.42) + Barrett.prototype.reduce = function (x) { + x.drShiftTo(this.m.t - 1, this.r2); + if (x.t > this.m.t + 1) { + x.t = this.m.t + 1; + x.clamp(); + } + this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3); + this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); + while (x.compareTo(this.r2) < 0) { + x.dAddOffset(1, this.m.t + 1); + } + x.subTo(this.r2, x); + while (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + }; + // Barrett.prototype.mulTo = barrettMulTo; + // r = x*y mod m; x,y != r + Barrett.prototype.mulTo = function (x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); + }; + // Barrett.prototype.sqrTo = barrettSqrTo; + // r = x^2 mod m; x != r + Barrett.prototype.sqrTo = function (x, r) { + x.squareTo(r); + this.reduce(r); + }; + return Barrett; +}()); +//#endregion +//#endregion REDUCERS +// return new, unset BigInteger +function nbi() { return new BigInteger(null); } +function parseBigInt(str, r) { + return new BigInteger(str, r); +} +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. +// am1: use a single mult and divide to get the high bits, +// max digit bits should be 26 because +// max internal value = 2*dvalue^2-2*dvalue (< 2^53) +function am1(i, x, w, j, c, n) { + while (--n >= 0) { + var v = x * this[i++] + w[j] + c; + c = Math.floor(v / 0x4000000); + w[j++] = v & 0x3ffffff; + } + return c; +} +// am2 avoids a big mult-and-extract completely. +// Max digit bits should be <= 30 because we do bitwise ops +// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) +function am2(i, x, w, j, c, n) { + var xl = x & 0x7fff; + var xh = x >> 15; + while (--n >= 0) { + var l = this[i] & 0x7fff; + var h = this[i++] >> 15; + var m = xh * l + h * xl; + l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff); + c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30); + w[j++] = l & 0x3fffffff; + } + return c; +} +// Alternately, set max digit bits to 28 since some +// browsers slow down when dealing with 32-bit numbers. +function am3(i, x, w, j, c, n) { + var xl = x & 0x3fff; + var xh = x >> 14; + while (--n >= 0) { + var l = this[i] & 0x3fff; + var h = this[i++] >> 14; + var m = xh * l + h * xl; + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c; + c = (l >> 28) + (m >> 14) + xh * h; + w[j++] = l & 0xfffffff; + } + return c; +} +// if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) { +// BigInteger.prototype.am = am2; +// dbits = 30; +// } +// else if (j_lm && (navigator.appName != "Netscape")) { +// BigInteger.prototype.am = am1; +// dbits = 26; +// } +// else { // Mozilla/Netscape seems to prefer am3 +// BigInteger.prototype.am = am3; +// dbits = 28; +// } +BigInteger.prototype.am = am1; +dbits = 26; + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1 << dbits) - 1); +BigInteger.prototype.DV = (1 << dbits); +var BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2, BI_FP); +BigInteger.prototype.F1 = BI_FP - dbits; +BigInteger.prototype.F2 = 2 * dbits - BI_FP; +// Digit conversions +var BI_RC = []; +var rr; +var vv; +rr = "0".charCodeAt(0); +for (vv = 0; vv <= 9; ++vv) { + BI_RC[rr++] = vv; +} +rr = "a".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} +rr = "A".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} +function intAt(s, i) { + var c = BI_RC[s.charCodeAt(i)]; + return (c == null) ? -1 : c; +} +// return bigint initialized to value +function nbv(i) { + var r = nbi(); + r.fromInt(i); + return r; +} +// returns bit length of the integer x +function nbits(x) { + var r = 1; + var t; + if ((t = x >>> 16) != 0) { + x = t; + r += 16; + } + if ((t = x >> 8) != 0) { + x = t; + r += 8; + } + if ((t = x >> 4) != 0) { + x = t; + r += 4; + } + if ((t = x >> 2) != 0) { + x = t; + r += 2; + } + if ((t = x >> 1) != 0) { + x = t; + r += 1; + } + return r; +} +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); + +// prng4.js - uses Arcfour as a PRNG +var Arcfour = /** @class */ (function () { + function Arcfour() { + this.i = 0; + this.j = 0; + this.S = []; + } + // Arcfour.prototype.init = ARC4init; + // Initialize arcfour context from key, an array of ints, each from [0..255] + Arcfour.prototype.init = function (key) { + var i; + var j; + var t; + for (i = 0; i < 256; ++i) { + this.S[i] = i; + } + j = 0; + for (i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; + }; + // Arcfour.prototype.next = ARC4next; + Arcfour.prototype.next = function () { + var t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; + }; + return Arcfour; +}()); +// Plug in your RNG constructor here +function prng_newstate() { + return new Arcfour(); +} +// Pool size must be a multiple of 4 and greater than 32. +// An array of bytes the size of the pool will be passed to init() +var rng_psize = 256; + +// Random number generator - requires a PRNG backend, e.g. prng4.js +var rng_state; +var rng_pool = null; +var rng_pptr; +// Initialize the pool with junk if needed. +if (rng_pool == null) { + rng_pool = []; + rng_pptr = 0; + var t = void 0; + if (window.crypto && window.crypto.getRandomValues) { + // Extract entropy (2048 bits) from RNG if available + var z = new Uint32Array(256); + window.crypto.getRandomValues(z); + for (t = 0; t < z.length; ++t) { + rng_pool[rng_pptr++] = z[t] & 255; + } + } + // Use mouse events for entropy, if we do not have enough entropy by the time + // we need it, entropy will be generated by Math.random. + var onMouseMoveListener_1 = function (ev) { + this.count = this.count || 0; + if (this.count >= 256 || rng_pptr >= rng_psize) { + if (window.removeEventListener) { + window.removeEventListener("mousemove", onMouseMoveListener_1, false); + } + else if (window.detachEvent) { + window.detachEvent("onmousemove", onMouseMoveListener_1); + } + return; + } + try { + var mouseCoordinates = ev.x + ev.y; + rng_pool[rng_pptr++] = mouseCoordinates & 255; + this.count += 1; + } + catch (e) { + // Sometimes Firefox will deny permission to access event properties for some reason. Ignore. + } + }; + if (window.addEventListener) { + window.addEventListener("mousemove", onMouseMoveListener_1, false); + } + else if (window.attachEvent) { + window.attachEvent("onmousemove", onMouseMoveListener_1); + } +} +function rng_get_byte() { + if (rng_state == null) { + rng_state = prng_newstate(); + // At this point, we may not have collected enough entropy. If not, fall back to Math.random + while (rng_pptr < rng_psize) { + var random = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = random & 255; + } + rng_state.init(rng_pool); + for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) { + rng_pool[rng_pptr] = 0; + } + rng_pptr = 0; + } + // TODO: allow reseeding after first request + return rng_state.next(); +} +var SecureRandom = /** @class */ (function () { + function SecureRandom() { + } + SecureRandom.prototype.nextBytes = function (ba) { + for (var i = 0; i < ba.length; ++i) { + ba[i] = rng_get_byte(); + } + }; + return SecureRandom; +}()); + +// Depends on jsbn.js and rng.js +// function linebrk(s,n) { +// var ret = ""; +// var i = 0; +// while(i + n < s.length) { +// ret += s.substring(i,i+n) + "\n"; +// i += n; +// } +// return ret + s.substring(i,s.length); +// } +// function byte2Hex(b) { +// if(b < 0x10) +// return "0" + b.toString(16); +// else +// return b.toString(16); +// } +function pkcs1pad1(s, n) { + if (n < s.length + 22) { + console.error("Message too long for RSA"); + return null; + } + var len = n - s.length - 6; + var filler = ""; + for (var f = 0; f < len; f += 2) { + filler += "ff"; + } + var m = "0001" + filler + "00" + s; + return parseBigInt(m, 16); +} +// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint +function pkcs1pad2(s, n) { + if (n < s.length + 11) { // TODO: fix for utf-8 + console.error("Message too long for RSA"); + return null; + } + var ba = []; + var i = s.length - 1; + while (i >= 0 && n > 0) { + var c = s.charCodeAt(i--); + if (c < 128) { // encode using utf-8 + ba[--n] = c; + } + else if ((c > 127) && (c < 2048)) { + ba[--n] = (c & 63) | 128; + ba[--n] = (c >> 6) | 192; + } + else { + ba[--n] = (c & 63) | 128; + ba[--n] = ((c >> 6) & 63) | 128; + ba[--n] = (c >> 12) | 224; + } + } + ba[--n] = 0; + var rng = new SecureRandom(); + var x = []; + while (n > 2) { // random non-zero pad + x[0] = 0; + while (x[0] == 0) { + rng.nextBytes(x); + } + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); +} +// "empty" RSA key constructor +var RSAKey = /** @class */ (function () { + function RSAKey() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; + } + //#region PROTECTED + // protected + // RSAKey.prototype.doPublic = RSADoPublic; + // Perform raw public operation on "x": return x^e (mod n) + RSAKey.prototype.doPublic = function (x) { + return x.modPowInt(this.e, this.n); + }; + // RSAKey.prototype.doPrivate = RSADoPrivate; + // Perform raw private operation on "x": return x^d (mod n) + RSAKey.prototype.doPrivate = function (x) { + if (this.p == null || this.q == null) { + return x.modPow(this.d, this.n); + } + // TODO: re-calculate any missing CRT params + var xp = x.mod(this.p).modPow(this.dmp1, this.p); + var xq = x.mod(this.q).modPow(this.dmq1, this.q); + while (xp.compareTo(xq) < 0) { + xp = xp.add(this.p); + } + return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); + }; + //#endregion PROTECTED + //#region PUBLIC + // RSAKey.prototype.setPublic = RSASetPublic; + // Set the public key fields N and e from hex strings + RSAKey.prototype.setPublic = function (N, E) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + } + else { + console.error("Invalid RSA public key"); + } + }; + // RSAKey.prototype.encrypt = RSAEncrypt; + // Return the PKCS#1 RSA encryption of "text" as an even-length hex string + RSAKey.prototype.encrypt = function (text) { + var m = pkcs1pad2(text, (this.n.bitLength() + 7) >> 3); + if (m == null) { + return null; + } + var c = this.doPublic(m); + if (c == null) { + return null; + } + var h = c.toString(16); + if ((h.length & 1) == 0) { + return h; + } + else { + return "0" + h; + } + }; + // RSAKey.prototype.setPrivate = RSASetPrivate; + // Set the private key fields N, e, and d from hex strings + RSAKey.prototype.setPrivate = function (N, E, D) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + } + else { + console.error("Invalid RSA private key"); + } + }; + // RSAKey.prototype.setPrivateEx = RSASetPrivateEx; + // Set the private key fields N, e, d and CRT params from hex strings + RSAKey.prototype.setPrivateEx = function (N, E, D, P, Q, DP, DQ, C) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + this.p = parseBigInt(P, 16); + this.q = parseBigInt(Q, 16); + this.dmp1 = parseBigInt(DP, 16); + this.dmq1 = parseBigInt(DQ, 16); + this.coeff = parseBigInt(C, 16); + } + else { + console.error("Invalid RSA private key"); + } + }; + // RSAKey.prototype.generate = RSAGenerate; + // Generate a new random private key B bits long, using public expt E + RSAKey.prototype.generate = function (B, E) { + var rng = new SecureRandom(); + var qs = B >> 1; + this.e = parseInt(E, 16); + var ee = new BigInteger(E, 16); + for (;;) { + for (;;) { + this.p = new BigInteger(B - qs, 1, rng); + if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) { + break; + } + } + for (;;) { + this.q = new BigInteger(qs, 1, rng); + if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) { + break; + } + } + if (this.p.compareTo(this.q) <= 0) { + var t = this.p; + this.p = this.q; + this.q = t; + } + var p1 = this.p.subtract(BigInteger.ONE); + var q1 = this.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + this.n = this.p.multiply(this.q); + this.d = ee.modInverse(phi); + this.dmp1 = this.d.mod(p1); + this.dmq1 = this.d.mod(q1); + this.coeff = this.q.modInverse(this.p); + break; + } + } + }; + // RSAKey.prototype.decrypt = RSADecrypt; + // Return the PKCS#1 RSA decryption of "ctext". + // "ctext" is an even-length hex string and the output is a plain string. + RSAKey.prototype.decrypt = function (ctext) { + var c = parseBigInt(ctext, 16); + var m = this.doPrivate(c); + if (m == null) { + return null; + } + return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3); + }; + // Generate a new random private key B bits long, using public expt E + RSAKey.prototype.generateAsync = function (B, E, callback) { + var rng = new SecureRandom(); + var qs = B >> 1; + this.e = parseInt(E, 16); + var ee = new BigInteger(E, 16); + var rsa = this; + // These functions have non-descript names because they were originally for(;;) loops. + // I don't know about cryptography to give them better names than loop1-4. + var loop1 = function () { + var loop4 = function () { + if (rsa.p.compareTo(rsa.q) <= 0) { + var t = rsa.p; + rsa.p = rsa.q; + rsa.q = t; + } + var p1 = rsa.p.subtract(BigInteger.ONE); + var q1 = rsa.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + rsa.n = rsa.p.multiply(rsa.q); + rsa.d = ee.modInverse(phi); + rsa.dmp1 = rsa.d.mod(p1); + rsa.dmq1 = rsa.d.mod(q1); + rsa.coeff = rsa.q.modInverse(rsa.p); + setTimeout(function () { callback(); }, 0); // escape + } + else { + setTimeout(loop1, 0); + } + }; + var loop3 = function () { + rsa.q = nbi(); + rsa.q.fromNumberAsync(qs, 1, rng, function () { + rsa.q.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) { + setTimeout(loop4, 0); + } + else { + setTimeout(loop3, 0); + } + }); + }); + }; + var loop2 = function () { + rsa.p = nbi(); + rsa.p.fromNumberAsync(B - qs, 1, rng, function () { + rsa.p.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) { + setTimeout(loop3, 0); + } + else { + setTimeout(loop2, 0); + } + }); + }); + }; + setTimeout(loop2, 0); + }; + setTimeout(loop1, 0); + }; + RSAKey.prototype.sign = function (text, digestMethod, digestName) { + var header = getDigestHeader(digestName); + var digest = header + digestMethod(text).toString(); + var m = pkcs1pad1(digest, this.n.bitLength() / 4); + if (m == null) { + return null; + } + var c = this.doPrivate(m); + if (c == null) { + return null; + } + var h = c.toString(16); + if ((h.length & 1) == 0) { + return h; + } + else { + return "0" + h; + } + }; + RSAKey.prototype.verify = function (text, signature, digestMethod) { + var c = parseBigInt(signature, 16); + var m = this.doPublic(c); + if (m == null) { + return null; + } + var unpadded = m.toString(16).replace(/^1f+00/, ""); + var digest = removeDigestHeader(unpadded); + return digest == digestMethod(text).toString(); + }; + return RSAKey; +}()); +// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext +function pkcs1unpad2(d, n) { + var b = d.toByteArray(); + var i = 0; + while (i < b.length && b[i] == 0) { + ++i; + } + if (b.length - i != n - 1 || b[i] != 2) { + return null; + } + ++i; + while (b[i] != 0) { + if (++i >= b.length) { + return null; + } + } + var ret = ""; + while (++i < b.length) { + var c = b[i] & 255; + if (c < 128) { // utf-8 decode + ret += String.fromCharCode(c); + } + else if ((c > 191) && (c < 224)) { + ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63)); + ++i; + } + else { + ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63)); + i += 2; + } + } + return ret; +} +// https://tools.ietf.org/html/rfc3447#page-43 +var DIGEST_HEADERS = { + md2: "3020300c06082a864886f70d020205000410", + md5: "3020300c06082a864886f70d020505000410", + sha1: "3021300906052b0e03021a05000414", + sha224: "302d300d06096086480165030402040500041c", + sha256: "3031300d060960864801650304020105000420", + sha384: "3041300d060960864801650304020205000430", + sha512: "3051300d060960864801650304020305000440", + ripemd160: "3021300906052b2403020105000414", +}; +function getDigestHeader(name) { + return DIGEST_HEADERS[name] || ""; +} +function removeDigestHeader(str) { + for (var name_1 in DIGEST_HEADERS) { + if (DIGEST_HEADERS.hasOwnProperty(name_1)) { + var header = DIGEST_HEADERS[name_1]; + var len = header.length; + if (str.substr(0, len) == header) { + return str.substr(len); + } + } + } + return str; +} +// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string +// function RSAEncryptB64(text) { +// var h = this.encrypt(text); +// if(h) return hex2b64(h); else return null; +// } +// public +// RSAKey.prototype.encrypt_b64 = RSAEncryptB64; + +/*! +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +var YAHOO = {}; +YAHOO.lang = { + /** + * Utility to set up the prototype, constructor and superclass properties to + * support an inheritance strategy that can chain constructors and methods. + * Static members will not be inherited. + * + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass + * if present. + */ + extend: function(subc, superc, overrides) { + if (! superc || ! subc) { + throw new Error("YAHOO.lang.extend failed, please check that " + + "all dependencies are included."); + } + + var F = function() {}; + F.prototype = superc.prototype; + subc.prototype = new F(); + subc.prototype.constructor = subc; + subc.superclass = superc.prototype; + + if (superc.prototype.constructor == Object.prototype.constructor) { + superc.prototype.constructor = superc; + } + + if (overrides) { + var i; + for (i in overrides) { + subc.prototype[i] = overrides[i]; + } + + /* + * IE will not enumerate native functions in a derived object even if the + * function was overridden. This is a workaround for specific functions + * we care about on the Object prototype. + * @property _IEEnumFix + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @static + * @private + */ + var _IEEnumFix = function() {}, + ADD = ["toString", "valueOf"]; + try { + if (/MSIE/.test(navigator.userAgent)) { + _IEEnumFix = function(r, s) { + for (i = 0; i < ADD.length; i = i + 1) { + var fname = ADD[i], f = s[fname]; + if (typeof f === 'function' && f != Object.prototype[fname]) { + r[fname] = f; + } + } + }; + } + } catch (ex) {} _IEEnumFix(subc.prototype, overrides); + } + } +}; + +/* asn1-1.0.13.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license + */ + +/** + * @fileOverview + * @name asn1-1.0.js + * @author Kenji Urushima kenji.urushima@gmail.com + * @version asn1 1.0.13 (2017-Jun-02) + * @since jsrsasign 2.1 + * @license MIT License + */ + +/** + * kjur's class library name space + *

+ * This name space provides following name spaces: + *

    + *
  • {@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder
  • + *
  • {@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL
  • + *
  • {@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature + * class and utilities
  • + *
+ *

+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. + * @name KJUR + * @namespace kjur's class library name space + */ +var KJUR = {}; + +/** + * kjur's ASN.1 class library name space + *

+ * This is ITU-T X.690 ASN.1 DER encoder class library and + * class structure and methods is very similar to + * org.bouncycastle.asn1 package of + * well known BouncyCaslte Cryptography Library. + *

PROVIDING ASN.1 PRIMITIVES

+ * Here are ASN.1 DER primitive classes. + *
    + *
  • 0x01 {@link KJUR.asn1.DERBoolean}
  • + *
  • 0x02 {@link KJUR.asn1.DERInteger}
  • + *
  • 0x03 {@link KJUR.asn1.DERBitString}
  • + *
  • 0x04 {@link KJUR.asn1.DEROctetString}
  • + *
  • 0x05 {@link KJUR.asn1.DERNull}
  • + *
  • 0x06 {@link KJUR.asn1.DERObjectIdentifier}
  • + *
  • 0x0a {@link KJUR.asn1.DEREnumerated}
  • + *
  • 0x0c {@link KJUR.asn1.DERUTF8String}
  • + *
  • 0x12 {@link KJUR.asn1.DERNumericString}
  • + *
  • 0x13 {@link KJUR.asn1.DERPrintableString}
  • + *
  • 0x14 {@link KJUR.asn1.DERTeletexString}
  • + *
  • 0x16 {@link KJUR.asn1.DERIA5String}
  • + *
  • 0x17 {@link KJUR.asn1.DERUTCTime}
  • + *
  • 0x18 {@link KJUR.asn1.DERGeneralizedTime}
  • + *
  • 0x30 {@link KJUR.asn1.DERSequence}
  • + *
  • 0x31 {@link KJUR.asn1.DERSet}
  • + *
+ *

OTHER ASN.1 CLASSES

+ *
    + *
  • {@link KJUR.asn1.ASN1Object}
  • + *
  • {@link KJUR.asn1.DERAbstractString}
  • + *
  • {@link KJUR.asn1.DERAbstractTime}
  • + *
  • {@link KJUR.asn1.DERAbstractStructured}
  • + *
  • {@link KJUR.asn1.DERTaggedObject}
  • + *
+ *

SUB NAME SPACES

+ *
    + *
  • {@link KJUR.asn1.cades} - CAdES long term signature format
  • + *
  • {@link KJUR.asn1.cms} - Cryptographic Message Syntax
  • + *
  • {@link KJUR.asn1.csr} - Certificate Signing Request (CSR/PKCS#10)
  • + *
  • {@link KJUR.asn1.tsp} - RFC 3161 Timestamping Protocol Format
  • + *
  • {@link KJUR.asn1.x509} - RFC 5280 X.509 certificate and CRL
  • + *
+ *

+ * NOTE: Please ignore method summary and document of this namespace. + * This caused by a bug of jsdoc2. + * @name KJUR.asn1 + * @namespace + */ +if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; + +/** + * ASN1 utilities class + * @name KJUR.asn1.ASN1Util + * @class ASN1 utilities class + * @since asn1 1.0.2 + */ +KJUR.asn1.ASN1Util = new function() { + this.integerToByteHex = function(i) { + var h = i.toString(16); + if ((h.length % 2) == 1) h = '0' + h; + return h; + }; + this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) { + var h = bigIntegerValue.toString(16); + if (h.substr(0, 1) != '-') { + if (h.length % 2 == 1) { + h = '0' + h; + } else { + if (! h.match(/^[0-7]/)) { + h = '00' + h; + } + } + } else { + var hPos = h.substr(1); + var xorLen = hPos.length; + if (xorLen % 2 == 1) { + xorLen += 1; + } else { + if (! h.match(/^[0-7]/)) { + xorLen += 2; + } + } + var hMask = ''; + for (var i = 0; i < xorLen; i++) { + hMask += 'f'; + } + var biMask = new BigInteger(hMask, 16); + var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE); + h = biNeg.toString(16).replace(/^-/, ''); + } + return h; + }; + /** + * get PEM string from hexadecimal data and header string + * @name getPEMStringFromHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} dataHex hexadecimal string of PEM body + * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') + * @return {String} PEM formatted string of input data + * @description + * This method converts a hexadecimal string to a PEM string with + * a specified header. Its line break will be CRLF("\r\n"). + * @example + * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY'); + * // value of pem will be: + * -----BEGIN PRIVATE KEY----- + * YWFh + * -----END PRIVATE KEY----- + */ + this.getPEMStringFromHex = function(dataHex, pemHeader) { + return hextopem(dataHex, pemHeader); + }; + + /** + * generate ASN1Object specifed by JSON parameters + * @name newObject + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return {KJUR.asn1.ASN1Object} generated object + * @since asn1 1.0.3 + * @description + * generate any ASN1Object specified by JSON param + * including ASN.1 primitive or structured. + * Generally 'param' can be described as follows: + *
+ * {TYPE-OF-ASNOBJ: ASN1OBJ-PARAMETER} + *
+ * 'TYPE-OF-ASN1OBJ' can be one of following symbols: + *
    + *
  • 'bool' - DERBoolean
  • + *
  • 'int' - DERInteger
  • + *
  • 'bitstr' - DERBitString
  • + *
  • 'octstr' - DEROctetString
  • + *
  • 'null' - DERNull
  • + *
  • 'oid' - DERObjectIdentifier
  • + *
  • 'enum' - DEREnumerated
  • + *
  • 'utf8str' - DERUTF8String
  • + *
  • 'numstr' - DERNumericString
  • + *
  • 'prnstr' - DERPrintableString
  • + *
  • 'telstr' - DERTeletexString
  • + *
  • 'ia5str' - DERIA5String
  • + *
  • 'utctime' - DERUTCTime
  • + *
  • 'gentime' - DERGeneralizedTime
  • + *
  • 'seq' - DERSequence
  • + *
  • 'set' - DERSet
  • + *
  • 'tag' - DERTaggedObject
  • + *
+ * @example + * newObject({'prnstr': 'aaa'}); + * newObject({'seq': [{'int': 3}, {'prnstr': 'aaa'}]}) + * // ASN.1 Tagged Object + * newObject({'tag': {'tag': 'a1', + * 'explicit': true, + * 'obj': {'seq': [{'int': 3}, {'prnstr': 'aaa'}]}}}); + * // more simple representation of ASN.1 Tagged Object + * newObject({'tag': ['a1', + * true, + * {'seq': [ + * {'int': 3}, + * {'prnstr': 'aaa'}]} + * ]}); + */ + this.newObject = function(param) { + var _KJUR = KJUR, + _KJUR_asn1 = _KJUR.asn1, + _DERBoolean = _KJUR_asn1.DERBoolean, + _DERInteger = _KJUR_asn1.DERInteger, + _DERBitString = _KJUR_asn1.DERBitString, + _DEROctetString = _KJUR_asn1.DEROctetString, + _DERNull = _KJUR_asn1.DERNull, + _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier, + _DEREnumerated = _KJUR_asn1.DEREnumerated, + _DERUTF8String = _KJUR_asn1.DERUTF8String, + _DERNumericString = _KJUR_asn1.DERNumericString, + _DERPrintableString = _KJUR_asn1.DERPrintableString, + _DERTeletexString = _KJUR_asn1.DERTeletexString, + _DERIA5String = _KJUR_asn1.DERIA5String, + _DERUTCTime = _KJUR_asn1.DERUTCTime, + _DERGeneralizedTime = _KJUR_asn1.DERGeneralizedTime, + _DERSequence = _KJUR_asn1.DERSequence, + _DERSet = _KJUR_asn1.DERSet, + _DERTaggedObject = _KJUR_asn1.DERTaggedObject, + _newObject = _KJUR_asn1.ASN1Util.newObject; + + var keys = Object.keys(param); + if (keys.length != 1) + throw "key of param shall be only one."; + var key = keys[0]; + + if (":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1) + throw "undefined key: " + key; + + if (key == "bool") return new _DERBoolean(param[key]); + if (key == "int") return new _DERInteger(param[key]); + if (key == "bitstr") return new _DERBitString(param[key]); + if (key == "octstr") return new _DEROctetString(param[key]); + if (key == "null") return new _DERNull(param[key]); + if (key == "oid") return new _DERObjectIdentifier(param[key]); + if (key == "enum") return new _DEREnumerated(param[key]); + if (key == "utf8str") return new _DERUTF8String(param[key]); + if (key == "numstr") return new _DERNumericString(param[key]); + if (key == "prnstr") return new _DERPrintableString(param[key]); + if (key == "telstr") return new _DERTeletexString(param[key]); + if (key == "ia5str") return new _DERIA5String(param[key]); + if (key == "utctime") return new _DERUTCTime(param[key]); + if (key == "gentime") return new _DERGeneralizedTime(param[key]); + + if (key == "seq") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSequence({'array': a}); + } + + if (key == "set") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSet({'array': a}); + } + + if (key == "tag") { + var tagParam = param[key]; + if (Object.prototype.toString.call(tagParam) === '[object Array]' && + tagParam.length == 3) { + var obj = _newObject(tagParam[2]); + return new _DERTaggedObject({tag: tagParam[0], + explicit: tagParam[1], + obj: obj}); + } else { + var newParam = {}; + if (tagParam.explicit !== undefined) + newParam.explicit = tagParam.explicit; + if (tagParam.tag !== undefined) + newParam.tag = tagParam.tag; + if (tagParam.obj === undefined) + throw "obj shall be specified for 'tag'."; + newParam.obj = _newObject(tagParam.obj); + return new _DERTaggedObject(newParam); + } + } + }; + + /** + * get encoded hexadecimal string of ASN1Object specifed by JSON parameters + * @name jsonToASN1HEX + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return hexadecimal string of ASN1Object + * @since asn1 1.0.4 + * @description + * As for ASN.1 object representation of JSON object, + * please see {@link newObject}. + * @example + * jsonToASN1HEX({'prnstr': 'aaa'}); + */ + this.jsonToASN1HEX = function(param) { + var asn1Obj = this.newObject(param); + return asn1Obj.getEncodedHex(); + }; +}; + +/** + * get dot noted oid number string from hexadecimal value of OID + * @name oidHexToInt + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} hex hexadecimal value of object identifier + * @return {String} dot noted string of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from hexadecimal string representation of + * ASN.1 value of object identifier to oid number string. + * @example + * KJUR.asn1.ASN1Util.oidHexToInt('550406') → "2.5.4.6" + */ +KJUR.asn1.ASN1Util.oidHexToInt = function(hex) { + var s = ""; + var i01 = parseInt(hex.substr(0, 2), 16); + var i0 = Math.floor(i01 / 40); + var i1 = i01 % 40; + var s = i0 + "." + i1; + + var binbuf = ""; + for (var i = 2; i < hex.length; i += 2) { + var value = parseInt(hex.substr(i, 2), 16); + var bin = ("00000000" + value.toString(2)).slice(- 8); + binbuf = binbuf + bin.substr(1, 7); + if (bin.substr(0, 1) == "0") { + var bi = new BigInteger(binbuf, 2); + s = s + "." + bi.toString(10); + binbuf = ""; + } + } + return s; +}; + +/** + * get hexadecimal value of object identifier from dot noted oid value + * @name oidIntToHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} oidString dot noted string of object identifier + * @return {String} hexadecimal value of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from object identifier value string. + * to hexadecimal string representation of it. + * @example + * KJUR.asn1.ASN1Util.oidIntToHex("2.5.4.6") → "550406" + */ +KJUR.asn1.ASN1Util.oidIntToHex = function(oidString) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + }; + + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + return h; +}; + + +// ******************************************************************** +// Abstract ASN.1 Classes +// ******************************************************************** + +// ******************************************************************** + +/** + * base class for ASN.1 DER encoder object + * @name KJUR.asn1.ASN1Object + * @class base class for ASN.1 DER encoder object + * @property {Boolean} isModified flag whether internal data was changed + * @property {String} hTLV hexadecimal string of ASN.1 TLV + * @property {String} hT hexadecimal string of ASN.1 TLV tag(T) + * @property {String} hL hexadecimal string of ASN.1 TLV length(L) + * @property {String} hV hexadecimal string of ASN.1 TLV value(V) + * @description + */ +KJUR.asn1.ASN1Object = function() { + var hV = ''; + + /** + * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V) + * @name getLengthHexFromValue + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV length(L) + */ + this.getLengthHexFromValue = function() { + if (typeof this.hV == "undefined" || this.hV == null) { + throw "this.hV is null or undefined."; + } + if (this.hV.length % 2 == 1) { + throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV; + } + var n = this.hV.length / 2; + var hN = n.toString(16); + if (hN.length % 2 == 1) { + hN = "0" + hN; + } + if (n < 128) { + return hN; + } else { + var hNlen = hN.length / 2; + if (hNlen > 15) { + throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16); + } + var head = 128 + hNlen; + return head.toString(16) + hN; + } + }; + + /** + * get hexadecimal string of ASN.1 TLV bytes + * @name getEncodedHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV + */ + this.getEncodedHex = function() { + if (this.hTLV == null || this.isModified) { + this.hV = this.getFreshValueHex(); + this.hL = this.getLengthHexFromValue(); + this.hTLV = this.hT + this.hL + this.hV; + this.isModified = false; + //alert("first time: " + this.hTLV); + } + return this.hTLV; + }; + + /** + * get hexadecimal string of ASN.1 TLV value(V) bytes + * @name getValueHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes + */ + this.getValueHex = function() { + this.getEncodedHex(); + return this.hV; + }; + + this.getFreshValueHex = function() { + return ''; + }; +}; + +// == BEGIN DERAbstractString ================================================ +/** + * base class for ASN.1 DER string classes + * @name KJUR.asn1.DERAbstractString + * @class base class for ASN.1 DER string classes + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @property {String} s internal string of value + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • str - specify initial ASN.1 value(V) by a string
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
+ * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERAbstractString = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @return {String} string value of this string object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newS value by a string to set + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(this.s); + }; + + /** + * set value by a hexadecimal string + * @name setStringHex + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newHexString value by a hexadecimal string to set + */ + this.setStringHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string") { + this.setString(params); + } else if (typeof params['str'] != "undefined") { + this.setString(params['str']); + } else if (typeof params['hex'] != "undefined") { + this.setStringHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object); +// == END DERAbstractString ================================================ + +// == BEGIN DERAbstractTime ================================================== +/** + * base class for ASN.1 DER Generalized/UTCTime class + * @name KJUR.asn1.DERAbstractTime + * @class base class for ASN.1 DER Generalized/UTCTime class + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractTime = function(params) { + KJUR.asn1.DERAbstractTime.superclass.constructor.call(this); + + // --- PRIVATE METHODS -------------------- + this.localDateToUTC = function(d) { + utc = d.getTime() + (d.getTimezoneOffset() * 60000); + var utcDate = new Date(utc); + return utcDate; + }; + + /* + * format date string by Data object + * @name formatDate + * @memberOf KJUR.asn1.AbstractTime; + * @param {Date} dateObject + * @param {string} type 'utc' or 'gen' + * @param {boolean} withMillis flag for with millisections or not + * @description + * 'withMillis' flag is supported from asn1 1.0.6. + */ + this.formatDate = function(dateObject, type, withMillis) { + var pad = this.zeroPadding; + var d = this.localDateToUTC(dateObject); + var year = String(d.getFullYear()); + if (type == 'utc') year = year.substr(2, 2); + var month = pad(String(d.getMonth() + 1), 2); + var day = pad(String(d.getDate()), 2); + var hour = pad(String(d.getHours()), 2); + var min = pad(String(d.getMinutes()), 2); + var sec = pad(String(d.getSeconds()), 2); + var s = year + month + day + hour + min + sec; + if (withMillis === true) { + var millis = d.getMilliseconds(); + if (millis != 0) { + var sMillis = pad(String(millis), 3); + sMillis = sMillis.replace(/[0]+$/, ""); + s = s + "." + sMillis; + } + } + return s + "Z"; + }; + + this.zeroPadding = function(s, len) { + if (s.length >= len) return s; + return new Array(len - s.length + 1).join('0') + s; + }; + + // --- PUBLIC METHODS -------------------- + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @return {String} string value of this time object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {String} newS value by a string to set such like "130430235959Z" + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(newS); + }; + + /** + * set value by a Date object + * @name setByDateValue + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {Integer} year year of date (ex. 2013) + * @param {Integer} month month of date between 1 and 12 (ex. 12) + * @param {Integer} day day of month + * @param {Integer} hour hours of date + * @param {Integer} min minutes of date + * @param {Integer} sec seconds of date + */ + this.setByDateValue = function(year, month, day, hour, min, sec) { + var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0)); + this.setByDate(dateObject); + }; + + this.getFreshValueHex = function() { + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object); +// == END DERAbstractTime ================================================== + +// == BEGIN DERAbstractStructured ============================================ +/** + * base class for ASN.1 DER structured class + * @name KJUR.asn1.DERAbstractStructured + * @class base class for ASN.1 DER structured class + * @property {Array} asn1Array internal array of ASN1Object + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractStructured = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + + /** + * set value by array of ASN1Object + * @name setByASN1ObjectArray + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {array} asn1ObjectArray array of ASN1Object to set + */ + this.setByASN1ObjectArray = function(asn1ObjectArray) { + this.hTLV = null; + this.isModified = true; + this.asn1Array = asn1ObjectArray; + }; + + /** + * append an ASN1Object to internal array + * @name appendASN1Object + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {ASN1Object} asn1Object to add + */ + this.appendASN1Object = function(asn1Object) { + this.hTLV = null; + this.isModified = true; + this.asn1Array.push(asn1Object); + }; + + this.asn1Array = new Array(); + if (typeof params != "undefined") { + if (typeof params['array'] != "undefined") { + this.asn1Array = params['array']; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object); + + +// ******************************************************************** +// ASN.1 Object Classes +// ******************************************************************** + +// ******************************************************************** +/** + * class for ASN.1 DER Boolean + * @name KJUR.asn1.DERBoolean + * @class class for ASN.1 DER Boolean + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERBoolean = function() { + KJUR.asn1.DERBoolean.superclass.constructor.call(this); + this.hT = "01"; + this.hTLV = "0101ff"; +}; +YAHOO.lang.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Integer + * @name KJUR.asn1.DERInteger + * @class class for ASN.1 DER Integer + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • int - specify initial ASN.1 value(V) by integer value
  • + *
  • bigint - specify initial ASN.1 value(V) by BigInteger object
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
+ * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERInteger = function(params) { + KJUR.asn1.DERInteger.superclass.constructor.call(this); + this.hT = "02"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DERInteger + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
+ * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + * @example + * new KJUR.asn1.DERInteger(123); + * new KJUR.asn1.DERInteger({'int': 123}); + * new KJUR.asn1.DERInteger({'hex': '1fad'}); + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['bigint'] != "undefined") { + this.setByBigInteger(params['bigint']); + } else if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER encoded BitString primitive + * @name KJUR.asn1.DERBitString + * @class class for ASN.1 DER encoded BitString primitive + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • bin - specify binary string (ex. '10111')
  • + *
  • array - specify array of boolean (ex. [true,false,true,true])
  • + *
  • hex - specify hexadecimal string of ASN.1 value(V) including unused bits
  • + *
  • obj - specify {@link KJUR.asn1.ASN1Util.newObject} + * argument for "BitString encapsulates" structure.
  • + *
+ * NOTE1: 'params' can be omitted.
+ * NOTE2: 'obj' parameter have been supported since + * asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25).
+ * @example + * // default constructor + * o = new KJUR.asn1.DERBitString(); + * // initialize with binary string + * o = new KJUR.asn1.DERBitString({bin: "1011"}); + * // initialize with boolean array + * o = new KJUR.asn1.DERBitString({array: [true,false,true,true]}); + * // initialize with hexadecimal string (04 is unused bits) + * o = new KJUR.asn1.DEROctetString({hex: "04bac0"}); + * // initialize with ASN1Util.newObject argument for encapsulated + * o = new KJUR.asn1.DERBitString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // BIT STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DERBitString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = "00" + o.getEncodedHex(); + } + KJUR.asn1.DERBitString.superclass.constructor.call(this); + this.hT = "03"; + + /** + * set ASN.1 value(V) by a hexadecimal string including unused bits + * @name setHexValueIncludingUnusedBits + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} newHexStringIncludingUnusedBits + */ + this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) { + this.hTLV = null; + this.isModified = true; + this.hV = newHexStringIncludingUnusedBits; + }; + + /** + * set ASN.1 value(V) by unused bit and hexadecimal string of value + * @name setUnusedBitsAndHexValue + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {Integer} unusedBits + * @param {String} hValue + */ + this.setUnusedBitsAndHexValue = function(unusedBits, hValue) { + if (unusedBits < 0 || 7 < unusedBits) { + throw "unused bits shall be from 0 to 7: u = " + unusedBits; + } + var hUnusedBits = "0" + unusedBits; + this.hTLV = null; + this.isModified = true; + this.hV = hUnusedBits + hValue; + }; + + /** + * set ASN.1 DER BitString by binary string
+ * @name setByBinaryString + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} binaryString binary value string (i.e. '10111') + * @description + * Its unused bits will be calculated automatically by length of + * 'binaryValue'.
+ * NOTE: Trailing zeros '0' will be ignored. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray("01011"); + */ + this.setByBinaryString = function(binaryString) { + binaryString = binaryString.replace(/0+$/, ''); + var unusedBits = 8 - binaryString.length % 8; + if (unusedBits == 8) unusedBits = 0; + for (var i = 0; i <= unusedBits; i++) { + binaryString += '0'; + } + var h = ''; + for (var i = 0; i < binaryString.length - 1; i += 8) { + var b = binaryString.substr(i, 8); + var x = parseInt(b, 2).toString(16); + if (x.length == 1) x = '0' + x; + h += x; + } + this.hTLV = null; + this.isModified = true; + this.hV = '0' + unusedBits + h; + }; + + /** + * set ASN.1 TLV value(V) by an array of boolean
+ * @name setByBooleanArray + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {array} booleanArray array of boolean (ex. [true, false, true]) + * @description + * NOTE: Trailing falses will be ignored in the ASN.1 DER Object. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray([false, true, false, true, true]); + */ + this.setByBooleanArray = function(booleanArray) { + var s = ''; + for (var i = 0; i < booleanArray.length; i++) { + if (booleanArray[i] == true) { + s += '1'; + } else { + s += '0'; + } + } + this.setByBinaryString(s); + }; + + /** + * generate an array of falses with specified length
+ * @name newFalseArray + * @memberOf KJUR.asn1.DERBitString + * @function + * @param {Integer} nLength length of array to generate + * @return {array} array of boolean falses + * @description + * This static method may be useful to initialize boolean array. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.newFalseArray(3) → [false, false, false] + */ + this.newFalseArray = function(nLength) { + var a = new Array(nLength); + for (var i = 0; i < nLength; i++) { + a[i] = false; + } + return a; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string" && params.toLowerCase().match(/^[0-9a-f]+$/)) { + this.setHexValueIncludingUnusedBits(params); + } else if (typeof params['hex'] != "undefined") { + this.setHexValueIncludingUnusedBits(params['hex']); + } else if (typeof params['bin'] != "undefined") { + this.setByBinaryString(params['bin']); + } else if (typeof params['array'] != "undefined") { + this.setByBooleanArray(params['array']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER OctetString
+ * @name KJUR.asn1.DEROctetString + * @class class for ASN.1 DER OctetString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * This class provides ASN.1 OctetString simple type.
+ * Supported "params" attributes are: + *
    + *
  • str - to set a string as a value
  • + *
  • hex - to set a hexadecimal string as a value
  • + *
  • obj - to set a encapsulated ASN.1 value by JSON object + * which is defined in {@link KJUR.asn1.ASN1Util.newObject}
  • + *
+ * NOTE: A parameter 'obj' have been supported + * for "OCTET STRING, encapsulates" structure. + * since asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25). + * @see KJUR.asn1.DERAbstractString - superclass + * @example + * // default constructor + * o = new KJUR.asn1.DEROctetString(); + * // initialize with string + * o = new KJUR.asn1.DEROctetString({str: "aaa"}); + * // initialize with hexadecimal string + * o = new KJUR.asn1.DEROctetString({hex: "616161"}); + * // initialize with ASN1Util.newObject argument + * o = new KJUR.asn1.DEROctetString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // OCTET STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DEROctetString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = o.getEncodedHex(); + } + KJUR.asn1.DEROctetString.superclass.constructor.call(this, params); + this.hT = "04"; +}; +YAHOO.lang.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER Null + * @name KJUR.asn1.DERNull + * @class class for ASN.1 DER Null + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERNull = function() { + KJUR.asn1.DERNull.superclass.constructor.call(this); + this.hT = "05"; + this.hTLV = "0500"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER ObjectIdentifier + * @name KJUR.asn1.DERObjectIdentifier + * @class class for ASN.1 DER ObjectIdentifier + * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'}) + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
+ * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERObjectIdentifier = function(params) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + }; + + KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this); + this.hT = "06"; + + /** + * set value by a hexadecimal string + * @name setValueHex + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} newHexString hexadecimal value of OID bytes + */ + this.setValueHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + /** + * set value by a OID string
+ * @name setValueOidString + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidString OID string (ex. 2.5.4.13) + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueOidString("2.5.4.13"); + */ + this.setValueOidString = function(oidString) { + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = h; + }; + + /** + * set value by a OID name + * @name setValueName + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidName OID name (ex. 'serverAuth') + * @since 1.0.1 + * @description + * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'. + * Otherwise raise error. + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueName("serverAuth"); + */ + this.setValueName = function(oidName) { + var oid = KJUR.asn1.x509.OID.name2oid(oidName); + if (oid !== '') { + this.setValueOidString(oid); + } else { + throw "DERObjectIdentifier oidName undefined: " + oidName; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (params !== undefined) { + if (typeof params === "string") { + if (params.match(/^[0-2].[0-9.]+$/)) { + this.setValueOidString(params); + } else { + this.setValueName(params); + } + } else if (params.oid !== undefined) { + this.setValueOidString(params.oid); + } else if (params.hex !== undefined) { + this.setValueHex(params.hex); + } else if (params.name !== undefined) { + this.setValueName(params.name); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Enumerated + * @name KJUR.asn1.DEREnumerated + * @class class for ASN.1 DER Enumerated + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • int - specify initial ASN.1 value(V) by integer value
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
+ * NOTE: 'params' can be omitted. + * @example + * new KJUR.asn1.DEREnumerated(123); + * new KJUR.asn1.DEREnumerated({int: 123}); + * new KJUR.asn1.DEREnumerated({hex: '1fad'}); + */ +KJUR.asn1.DEREnumerated = function(params) { + KJUR.asn1.DEREnumerated.superclass.constructor.call(this); + this.hT = "0a"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
+ * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER UTF8String + * @name KJUR.asn1.DERUTF8String + * @class class for ASN.1 DER UTF8String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERUTF8String = function(params) { + KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params); + this.hT = "0c"; +}; +YAHOO.lang.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER NumericString + * @name KJUR.asn1.DERNumericString + * @class class for ASN.1 DER NumericString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERNumericString = function(params) { + KJUR.asn1.DERNumericString.superclass.constructor.call(this, params); + this.hT = "12"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER PrintableString + * @name KJUR.asn1.DERPrintableString + * @class class for ASN.1 DER PrintableString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERPrintableString = function(params) { + KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params); + this.hT = "13"; +}; +YAHOO.lang.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER TeletexString + * @name KJUR.asn1.DERTeletexString + * @class class for ASN.1 DER TeletexString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERTeletexString = function(params) { + KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params); + this.hT = "14"; +}; +YAHOO.lang.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER IA5String + * @name KJUR.asn1.DERIA5String + * @class class for ASN.1 DER IA5String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERIA5String = function(params) { + KJUR.asn1.DERIA5String.superclass.constructor.call(this, params); + this.hT = "16"; +}; +YAHOO.lang.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER UTCTime + * @name KJUR.asn1.DERUTCTime + * @class class for ASN.1 DER UTCTime + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.DERAbstractTime + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
  • date - specify Date object.
  • + *
+ * NOTE: 'params' can be omitted. + *

EXAMPLES

+ * @example + * d1 = new KJUR.asn1.DERUTCTime(); + * d1.setString('130430125959Z'); + * + * d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'}); + * d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))}); + * d4 = new KJUR.asn1.DERUTCTime('130430125959Z'); + */ +KJUR.asn1.DERUTCTime = function(params) { + KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params); + this.hT = "17"; + + /** + * set value by a Date object
+ * @name setByDate + * @memberOf KJUR.asn1.DERUTCTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * o = new KJUR.asn1.DERUTCTime(); + * o.setByDate(new Date("2016/12/31")); + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (typeof this.date == "undefined" && typeof this.s == "undefined") { + this.date = new Date(); + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER GeneralizedTime + * @name KJUR.asn1.DERGeneralizedTime + * @class class for ASN.1 DER GeneralizedTime + * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'}) + * @property {Boolean} withMillis flag to show milliseconds or not + * @extends KJUR.asn1.DERAbstractTime + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')
  • + *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • + *
  • date - specify Date object.
  • + *
  • millis - specify flag to show milliseconds (from 1.0.6)
  • + *
+ * NOTE1: 'params' can be omitted. + * NOTE2: 'withMillis' property is supported from asn1 1.0.6. + */ +KJUR.asn1.DERGeneralizedTime = function(params) { + KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params); + this.hT = "18"; + this.withMillis = false; + + /** + * set value by a Date object + * @name setByDate + * @memberOf KJUR.asn1.DERGeneralizedTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * When you specify UTC time, use 'Date.UTC' method like this:
+ * o1 = new DERUTCTime(); + * o1.setByDate(date); + * + * date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59 + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (this.date === undefined && this.s === undefined) { + this.date = new Date(); + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + if (params.millis === true) { + this.withMillis = true; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER Sequence + * @name KJUR.asn1.DERSequence + * @class class for ASN.1 DER Sequence + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • array - specify array of ASN1Object to set elements of content
  • + *
+ * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERSequence = function(params) { + KJUR.asn1.DERSequence.superclass.constructor.call(this, params); + this.hT = "30"; + this.getFreshValueHex = function() { + var h = ''; + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + h += asn1Obj.getEncodedHex(); + } + this.hV = h; + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER Set + * @name KJUR.asn1.DERSet + * @class class for ASN.1 DER Set + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
+ * As for argument 'params' for constructor, you can specify one of + * following properties: + *
    + *
  • array - specify array of ASN1Object to set elements of content
  • + *
  • sortflag - flag for sort (default: true). ASN.1 BER is not sorted in 'SET OF'.
  • + *
+ * NOTE1: 'params' can be omitted.
+ * NOTE2: sortflag is supported since 1.0.5. + */ +KJUR.asn1.DERSet = function(params) { + KJUR.asn1.DERSet.superclass.constructor.call(this, params); + this.hT = "31"; + this.sortFlag = true; // item shall be sorted only in ASN.1 DER + this.getFreshValueHex = function() { + var a = new Array(); + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + a.push(asn1Obj.getEncodedHex()); + } + if (this.sortFlag == true) a.sort(); + this.hV = a.join(''); + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params.sortflag != "undefined" && + params.sortflag == false) + this.sortFlag = false; + } +}; +YAHOO.lang.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER TaggedObject + * @name KJUR.asn1.DERTaggedObject + * @class class for ASN.1 DER TaggedObject + * @extends KJUR.asn1.ASN1Object + * @description + *
+ * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object. + * For example, if you find '[1]' tag in a ASN.1 dump, + * 'tagNoHex' will be 'a1'. + *
+ * As for optional argument 'params' for constructor, you can specify *ANY* of + * following properties: + *
    + *
  • explicit - specify true if this is explicit tag otherwise false + * (default is 'true').
  • + *
  • tag - specify tag (default is 'a0' which means [0])
  • + *
  • obj - specify ASN1Object which is tagged
  • + *
+ * @example + * d1 = new KJUR.asn1.DERUTF8String({'str':'a'}); + * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1}); + * hex = d2.getEncodedHex(); + */ +KJUR.asn1.DERTaggedObject = function(params) { + KJUR.asn1.DERTaggedObject.superclass.constructor.call(this); + this.hT = "a0"; + this.hV = ''; + this.isExplicit = true; + this.asn1Object = null; + + /** + * set value by an ASN1Object + * @name setString + * @memberOf KJUR.asn1.DERTaggedObject# + * @function + * @param {Boolean} isExplicitFlag flag for explicit/implicit tag + * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag + * @param {ASN1Object} asn1Object ASN.1 to encapsulate + */ + this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) { + this.hT = tagNoHex; + this.isExplicit = isExplicitFlag; + this.asn1Object = asn1Object; + if (this.isExplicit) { + this.hV = this.asn1Object.getEncodedHex(); + this.hTLV = null; + this.isModified = true; + } else { + this.hV = null; + this.hTLV = asn1Object.getEncodedHex(); + this.hTLV = this.hTLV.replace(/^../, tagNoHex); + this.isModified = false; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['tag'] != "undefined") { + this.hT = params['tag']; + } + if (typeof params['explicit'] != "undefined") { + this.isExplicit = params['explicit']; + } + if (typeof params['obj'] != "undefined") { + this.asn1Object = params['obj']; + this.setASN1Object(this.isExplicit, this.hT, this.asn1Object); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object); + +/** + * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object. + * This object is just a decorator for parsing the key parameter + * @param {string|Object} key - The key in string format, or an object containing + * the parameters needed to build a RSAKey object. + * @constructor + */ +var JSEncryptRSAKey = /** @class */ (function (_super) { + __extends(JSEncryptRSAKey, _super); + function JSEncryptRSAKey(key) { + var _this = _super.call(this) || this; + // Call the super constructor. + // RSAKey.call(this); + // If a key key was provided. + if (key) { + // If this is a string... + if (typeof key === "string") { + _this.parseKey(key); + } + else if (JSEncryptRSAKey.hasPrivateKeyProperty(key) || + JSEncryptRSAKey.hasPublicKeyProperty(key)) { + // Set the values for the key. + _this.parsePropertiesFrom(key); + } + } + return _this; + } + /** + * Method to parse a pem encoded string containing both a public or private key. + * The method will translate the pem encoded string in a der encoded string and + * will parse private key and public key parameters. This method accepts public key + * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1). + * + * @todo Check how many rsa formats use the same format of pkcs #1. + * + * The format is defined as: + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * it's possible to examine the structure of the keys obtained from openssl using + * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/ + * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer + * @private + */ + JSEncryptRSAKey.prototype.parseKey = function (pem) { + try { + var modulus = 0; + var public_exponent = 0; + var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/; + var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem); + var asn1 = ASN1.decode(der); + // Fixes a bug with OpenSSL 1.0+ private keys + if (asn1.sub.length === 3) { + asn1 = asn1.sub[2].sub[0]; + } + if (asn1.sub.length === 9) { + // Parse the private key. + modulus = asn1.sub[1].getHexStringValue(); // bigint + this.n = parseBigInt(modulus, 16); + public_exponent = asn1.sub[2].getHexStringValue(); // int + this.e = parseInt(public_exponent, 16); + var private_exponent = asn1.sub[3].getHexStringValue(); // bigint + this.d = parseBigInt(private_exponent, 16); + var prime1 = asn1.sub[4].getHexStringValue(); // bigint + this.p = parseBigInt(prime1, 16); + var prime2 = asn1.sub[5].getHexStringValue(); // bigint + this.q = parseBigInt(prime2, 16); + var exponent1 = asn1.sub[6].getHexStringValue(); // bigint + this.dmp1 = parseBigInt(exponent1, 16); + var exponent2 = asn1.sub[7].getHexStringValue(); // bigint + this.dmq1 = parseBigInt(exponent2, 16); + var coefficient = asn1.sub[8].getHexStringValue(); // bigint + this.coeff = parseBigInt(coefficient, 16); + } + else if (asn1.sub.length === 2) { + // Parse the public key. + var bit_string = asn1.sub[1]; + var sequence = bit_string.sub[0]; + modulus = sequence.sub[0].getHexStringValue(); + this.n = parseBigInt(modulus, 16); + public_exponent = sequence.sub[1].getHexStringValue(); + this.e = parseInt(public_exponent, 16); + } + else { + return false; + } + return true; + } + catch (ex) { + return false; + } + }; + /** + * Translate rsa parameters in a hex encoded string representing the rsa key. + * + * The translation follow the ASN.1 notation : + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * @returns {string} DER Encoded String representing the rsa private key + * @private + */ + JSEncryptRSAKey.prototype.getPrivateBaseKey = function () { + var options = { + array: [ + new KJUR.asn1.DERInteger({ int: 0 }), + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }), + new KJUR.asn1.DERInteger({ bigint: this.d }), + new KJUR.asn1.DERInteger({ bigint: this.p }), + new KJUR.asn1.DERInteger({ bigint: this.q }), + new KJUR.asn1.DERInteger({ bigint: this.dmp1 }), + new KJUR.asn1.DERInteger({ bigint: this.dmq1 }), + new KJUR.asn1.DERInteger({ bigint: this.coeff }) + ] + }; + var seq = new KJUR.asn1.DERSequence(options); + return seq.getEncodedHex(); + }; + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + JSEncryptRSAKey.prototype.getPrivateBaseKeyB64 = function () { + return hex2b64(this.getPrivateBaseKey()); + }; + /** + * Translate rsa parameters in a hex encoded string representing the rsa public key. + * The representation follow the ASN.1 notation : + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * @returns {string} DER Encoded String representing the rsa public key + * @private + */ + JSEncryptRSAKey.prototype.getPublicBaseKey = function () { + var first_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }), + new KJUR.asn1.DERNull() + ] + }); + var second_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }) + ] + }); + var bit_string = new KJUR.asn1.DERBitString({ + hex: "00" + second_sequence.getEncodedHex() + }); + var seq = new KJUR.asn1.DERSequence({ + array: [ + first_sequence, + bit_string + ] + }); + return seq.getEncodedHex(); + }; + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + JSEncryptRSAKey.prototype.getPublicBaseKeyB64 = function () { + return hex2b64(this.getPublicBaseKey()); + }; + /** + * wrap the string in block of width chars. The default value for rsa keys is 64 + * characters. + * @param {string} str the pem encoded string without header and footer + * @param {Number} [width=64] - the length the string has to be wrapped at + * @returns {string} + * @private + */ + JSEncryptRSAKey.wordwrap = function (str, width) { + width = width || 64; + if (!str) { + return str; + } + var regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})"; + return str.match(RegExp(regex, "g")).join("\n"); + }; + /** + * Retrieve the pem encoded private key + * @returns {string} the pem encoded private key with header/footer + * @public + */ + JSEncryptRSAKey.prototype.getPrivateKey = function () { + var key = "-----BEGIN RSA PRIVATE KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + "\n"; + key += "-----END RSA PRIVATE KEY-----"; + return key; + }; + /** + * Retrieve the pem encoded public key + * @returns {string} the pem encoded public key with header/footer + * @public + */ + JSEncryptRSAKey.prototype.getPublicKey = function () { + var key = "-----BEGIN PUBLIC KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + "\n"; + key += "-----END PUBLIC KEY-----"; + return key; + }; + /** + * Check if the object contains the necessary parameters to populate the rsa modulus + * and public exponent parameters. + * @param {Object} [obj={}] - An object that may contain the two public key + * parameters + * @returns {boolean} true if the object contains both the modulus and the public exponent + * properties (n and e) + * @todo check for types of n and e. N should be a parseable bigInt object, E should + * be a parseable integer number + * @private + */ + JSEncryptRSAKey.hasPublicKeyProperty = function (obj) { + obj = obj || {}; + return (obj.hasOwnProperty("n") && + obj.hasOwnProperty("e")); + }; + /** + * Check if the object contains ALL the parameters of an RSA key. + * @param {Object} [obj={}] - An object that may contain nine rsa key + * parameters + * @returns {boolean} true if the object contains all the parameters needed + * @todo check for types of the parameters all the parameters but the public exponent + * should be parseable bigint objects, the public exponent should be a parseable integer number + * @private + */ + JSEncryptRSAKey.hasPrivateKeyProperty = function (obj) { + obj = obj || {}; + return (obj.hasOwnProperty("n") && + obj.hasOwnProperty("e") && + obj.hasOwnProperty("d") && + obj.hasOwnProperty("p") && + obj.hasOwnProperty("q") && + obj.hasOwnProperty("dmp1") && + obj.hasOwnProperty("dmq1") && + obj.hasOwnProperty("coeff")); + }; + /** + * Parse the properties of obj in the current rsa object. Obj should AT LEAST + * include the modulus and public exponent (n, e) parameters. + * @param {Object} obj - the object containing rsa parameters + * @private + */ + JSEncryptRSAKey.prototype.parsePropertiesFrom = function (obj) { + this.n = obj.n; + this.e = obj.e; + if (obj.hasOwnProperty("d")) { + this.d = obj.d; + this.p = obj.p; + this.q = obj.q; + this.dmp1 = obj.dmp1; + this.dmq1 = obj.dmq1; + this.coeff = obj.coeff; + } + }; + return JSEncryptRSAKey; +}(RSAKey)); + +/** + * + * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour + * possible parameters are: + * - default_key_size {number} default: 1024 the key size in bit + * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent + * - log {boolean} default: false whether log warn/error or not + * @constructor + */ +var JSEncrypt = /** @class */ (function () { + function JSEncrypt(options) { + options = options || {}; + this.default_key_size = parseInt(options.default_key_size, 10) || 1024; + this.default_public_exponent = options.default_public_exponent || "010001"; // 65537 default openssl public exponent for rsa key type + this.log = options.log || false; + // The private and public key. + this.key = null; + } + /** + * Method to set the rsa key parameter (one method is enough to set both the public + * and the private key, since the private key contains the public key paramenters) + * Log a warning if logs are enabled + * @param {Object|string} key the pem encoded string or an object (with or without header/footer) + * @public + */ + JSEncrypt.prototype.setKey = function (key) { + if (this.log && this.key) { + console.warn("A key was already set, overriding existing."); + } + this.key = new JSEncryptRSAKey(key); + }; + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + JSEncrypt.prototype.setPrivateKey = function (privkey) { + // Create the key. + this.setKey(privkey); + }; + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + JSEncrypt.prototype.setPublicKey = function (pubkey) { + // Sets the public key. + this.setKey(pubkey); + }; + /** + * Proxy method for RSAKey object's decrypt, decrypt the string using the private + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str base64 encoded crypted string to decrypt + * @return {string} the decrypted string + * @public + */ + JSEncrypt.prototype.decrypt = function (str) { + // Return the decrypted string. + try { + return this.getKey().decrypt(b64tohex(str)); + } + catch (ex) { + return false; + } + }; + /** + * Proxy method for RSAKey object's encrypt, encrypt the string using the public + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str the string to encrypt + * @return {string} the encrypted string encoded in base64 + * @public + */ + JSEncrypt.prototype.encrypt = function (str) { + // Return the encrypted string. + try { + return hex2b64(this.getKey().encrypt(str)); + } + catch (ex) { + return false; + } + }; + /** + * Proxy method for RSAKey object's sign. + * @param {string} str the string to sign + * @param {function} digestMethod hash method + * @param {string} digestName the name of the hash algorithm + * @return {string} the signature encoded in base64 + * @public + */ + JSEncrypt.prototype.sign = function (str, digestMethod, digestName) { + // return the RSA signature of 'str' in 'hex' format. + try { + return hex2b64(this.getKey().sign(str, digestMethod, digestName)); + } + catch (ex) { + return false; + } + }; + /** + * Proxy method for RSAKey object's verify. + * @param {string} str the string to verify + * @param {string} signature the signature encoded in base64 to compare the string to + * @param {function} digestMethod hash method + * @return {boolean} whether the data and signature match + * @public + */ + JSEncrypt.prototype.verify = function (str, signature, digestMethod) { + // Return the decrypted 'digest' of the signature. + try { + return this.getKey().verify(str, b64tohex(signature), digestMethod); + } + catch (ex) { + return false; + } + }; + /** + * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object + * will be created and returned + * @param {callback} [cb] the callback to be called if we want the key to be generated + * in an async fashion + * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object + * @public + */ + JSEncrypt.prototype.getKey = function (cb) { + // Only create new if it does not exist. + if (!this.key) { + // Get a new private key. + this.key = new JSEncryptRSAKey(); + if (cb && {}.toString.call(cb) === "[object Function]") { + this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb); + return; + } + // Generate the key. + this.key.generate(this.default_key_size, this.default_public_exponent); + } + return this.key; + }; + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITH header and footer + * @public + */ + JSEncrypt.prototype.getPrivateKey = function () { + // Return the private representation of this key. + return this.getKey().getPrivateKey(); + }; + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITHOUT header and footer + * @public + */ + JSEncrypt.prototype.getPrivateKeyB64 = function () { + // Return the private representation of this key. + return this.getKey().getPrivateBaseKeyB64(); + }; + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITH header and footer + * @public + */ + JSEncrypt.prototype.getPublicKey = function () { + // Return the private representation of this key. + return this.getKey().getPublicKey(); + }; + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITHOUT header and footer + * @public + */ + JSEncrypt.prototype.getPublicKeyB64 = function () { + // Return the private representation of this key. + return this.getKey().getPublicBaseKeyB64(); + }; + JSEncrypt.version = "3.0.0-rc.1"; + return JSEncrypt; +}()); + +window.JSEncrypt = JSEncrypt; + +exports.JSEncrypt = JSEncrypt; +exports.default = JSEncrypt; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/d2d_app/client/js/myApps.js b/d2d_app/client/js/myApps.js new file mode 100755 index 00000000..9ea61141 --- /dev/null +++ b/d2d_app/client/js/myApps.js @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +"use strict"; +import { UpdateWebClip } from './app.js'; +import Actions from './actions.js'; + +const serverPort = 9000; +const serverURL = window.location.protocol + '//' + window.location.hostname; +const actions = new Actions(); +const NEW_WINDOW_TIMEOUT = 1000; +const myappsmodule = {}; + +(function () { + var xhr; + function emptyElement(elm) { + while (elm.firstChild) { + elm.removeChild(elm.firstChild); + } + return elm; + } + /** + * Open app in new window + * @param {Object} response + * @private + */ + function openAppWindow(response) { + document.getElementById("page-main").style.display = "none"; + var timer = setTimeout(function () { + clearTimeout(timer); + document.getElementById("page-main").style.display = "block"; + window.open(serverURL + ':' + response.port + '/app', 'newWindow'); + }, NEW_WINDOW_TIMEOUT); + }; + + function showListView(dataArray) { + var formResult = document.getElementById("d2dApps"), + imgResult = document.getElementById("d2dAppList"), + formObj, + imgObj, + textObj, + objTable, + objRow, + i, + d2dApp, + icon; + + emptyElement(imgResult); + + objTable = document.createElement("div"); + objTable.className = "result-table"; + + if (dataArray.length > 0) { + for (i = 0; i < dataArray.length; i++) { + formObj = document.createElement("div"); + imgObj = document.createElement("img"); + textObj = document.createElement("p"); + formObj.style.textAlign = "center"; + d2dApp = dataArray[i]['d2dApp']; + if (d2dApp.hasOwnProperty("appName")) { + if (d2dApp.iconPath) { + icon = d2dApp.iconPath.substring(d2dApp.iconPath.indexOf('/',10)+1); + imgObj.src = `/d2dIcon/${icon}`; + } else { + imgObj.src = `./images/icon.png`; + } + imgObj.className = "app-icon-img"; + imgObj.alt = d2dApp.appName; + textObj.style.display = "block"; + textObj.style.margin = "0 auto"; + textObj.style.fontSize = "14px"; + textObj.innerHTML = d2dApp.appName; + } + imgObj.addEventListener("click", actions.launchAppOnTV( + d2dApp.appPkgID, + d2dApp.appAppID, + function (response) { + openAppWindow(response); + })); + formObj.appendChild(imgObj); + formObj.appendChild(textObj); + + imgResult.appendChild(formObj); + } + formResult.appendChild(imgResult); + } else { + objRow = document.createElement("div"); + objRow.className = "result-table-error"; + objRow.appendChild(document.createTextNode("No Data")); + objTable.appendChild(objRow); + } + } + + function showList() { + xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState === xhr.DONE) { + if (xhr.status === 200 || xhr.status === 201) { + showListView(JSON.parse(xhr.responseText)); + } else { + console.error(xhr.responseText); + } + } + }; + xhr.open('GET', serverURL + ':' + serverPort + '/appList'); + xhr.send(); + } + + function init() { + var eventSource = new EventSource(serverURL + ':' + serverPort + '/updateAppList'); + eventSource.addEventListener('message', evt => { + showListView(JSON.parse(evt.data)); + UpdateWebClip(JSON.parse(evt.data)); + }, false); + eventSource.addEventListener('open', evt => { + console.log("Connected to..."); + }, false); + eventSource.addEventListener('error', evt => { + if (evt.target.readyState == EventSource.CLOSED) { + console.log("Disconnected from..."); + } else if (evt.target.readyState == EventSource.CONNECTING) { + console.log('Connecting to...'); + } + }, false); + showList(); + } + window.onload = init; + myappsmodule.openAppWindow = openAppWindow; +}()); + +export function openAppWindow(response) { + myappsmodule.openAppWindow(response); +}; + diff --git a/d2d_app/client/js/pincode.js b/d2d_app/client/js/pincode.js new file mode 100755 index 00000000..c1a49fe9 --- /dev/null +++ b/d2d_app/client/js/pincode.js @@ -0,0 +1,99 @@ +const serverPort = 9000; +const serverURL = window.location.protocol + '//' + window.location.hostname; + +var publicKey; +var input = ''; +var dots = document.querySelectorAll('.dot'), numbers = document.querySelectorAll('.number'); + +function preloadKey() { + var xhr = new XMLHttpRequest(); + xhr.onload = function () { + if (xhr.status === 200 || xhr.status === 201) { + publicKey = xhr.responseText; + if (publicKey) { + init(); + } else { + console.error('[WT] Failed to get public key.'); + } + } else { + console.error(xhr.responseText); + } + }; + xhr.open('GET', serverURL + ':' + serverPort + '/publicKey'); + xhr.send(); +} + +function init() { + dots = Array.prototype.slice.call(dots); + numbers = Array.prototype.slice.call(numbers); + numbers.forEach(function (number, index) { + number.addEventListener('click', function () { + number.className += ' grow'; + if (number.innerHTML === '0') { + input += 0; + } else { + input += index + 1; + } + dots[input.length - 1].className += ' active'; + if (input.length >= 4) { + sendPinCode(input); + + setTimeout(function () { + dots.forEach(function (dot, index) { + dot.className = 'dot'; + }); + input = ''; + }, 900); + setTimeout(function () { + document.body.className = ''; + }, 1000); + } + setTimeout(function () { + number.className = 'number'; + }, 1000); + }); + }); +} + +function sendPinCode(data) { + var encrypt = new JSEncrypt(); + encrypt.setPublicKey(publicKey); + var xhr = new XMLHttpRequest(); + xhr.onload = function () { + if (xhr.status === 200 || xhr.status === 201) { + console.log(`result : ${xhr.responseText}`); + chkPinCode(xhr.responseText === 'true' ? true : false); + } else { + console.error(xhr.responseText); + } + }; + xhr.open('POST', serverURL + ':' + serverPort + '/pinCodeToServer'); + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.send(encrypt.encrypt(data)); +} + +function chkPinCode(returnVal) { + if (returnVal) { + dots.forEach(function (dot, index) { + dot.className += ' correct'; + }); + document.body.className += ' correct'; + setTimeout(function () { + loginForm.submit(); + //pinCode(); + }, 1000); + } else { + dots.forEach(function (dot, index) { + dot.className += ' wrong'; + }); + document.body.className += ' wrong'; + } +} + +function pinCode() { + window.location.href = serverURL + ':' + serverPort + '/client/client.html'; +} + +window.onload = function () { + preloadKey(); +}; diff --git a/d2d_app/client/lib/tau/LICENSE.Flora b/d2d_app/client/lib/tau/LICENSE.Flora new file mode 100644 index 00000000..4ab7e534 --- /dev/null +++ b/d2d_app/client/lib/tau/LICENSE.Flora @@ -0,0 +1,206 @@ +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and +all other entities that control, are controlled by, or are +under common control with that entity. For the purposes of +this definition, "control" means (i) the power, direct or indirect, +to cause the direction or management of such entity, +whether by contract or otherwise, or (ii) ownership of fifty percent (50%) +or more of the outstanding shares, or (iii) beneficial ownership of +such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice +that is included in or attached to the work (an example is provided +in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, +or merely link (or bind by name) to the interfaces of, the Work and +Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor +for inclusion in the Work by the copyright owner or by an individual or +Legal Entity authorized to submit on behalf of the copyright owner. +For the purposes of this definition, "submitted" means any form of +electronic, verbal, or written communication sent to the Licensor or +its representatives, including but not limited to communication on +electronic mailing lists, source code control systems, and issue +tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding +communication that is conspicuously marked or otherwise designated +in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +"Tizen Certified Platform" shall mean a software platform that complies +with the standards set forth in the Tizen Compliance Specification +and passes the Tizen Compliance Tests as defined from time to time +by the Tizen Technical Steering Group and certified by the Tizen +Association or its designated agent. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work +solely as incorporated into a Tizen Certified Platform, where such +license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work solely +as incorporated into a Tizen Certified Platform to which such +Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent infringement, +then any patent licenses granted to You under this License for that +Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof pursuant to the copyright license +above, in any medium, with or without modifications, and in Source or +Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works + a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + 3. You must retain, in the Source form of any Derivative Works that + You distribute, all copyright, patent, trademark, and attribution + notices from the Source form of the Work, excluding those notices + that do not pertain to any part of the Derivative Works; and + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of + the Derivative Works, in at least one of the following places: + within a NOTICE text file distributed as part of the Derivative Works; + within the Source form or documentation, if provided along with the + Derivative Works; or, within a display generated by the Derivative Works, + if and wherever such third-party notices normally appear. + The contents of the NOTICE file are for informational purposes only + and do not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an addendum + to the NOTICE text from the Work, provided that such additional attribution + notices cannot be construed as modifying the License. You may add Your own + copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or + distribution of Your modifications, or for any such Derivative Works + as a whole, provided Your use, reproduction, and distribution of + the Work otherwise complies with the conditions stated in this License + and your own copyright statement or terms and conditions do not conflict + the conditions stated in the License including section 3. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Flora License to your work + +To apply the Flora License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright 2015 Samsung Electronics Co., Ltd. + + Licensed under the Flora License, Version 1.1 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://floralicense.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/d2d_app/client/lib/tau/VERSION b/d2d_app/client/lib/tau/VERSION new file mode 100644 index 00000000..c813fe11 --- /dev/null +++ b/d2d_app/client/lib/tau/VERSION @@ -0,0 +1 @@ +1.2.5 diff --git a/d2d_app/client/lib/tau/animation/tau.animation.js b/d2d_app/client/lib/tau/animation/tau.animation.js new file mode 100644 index 00000000..c6bb11a9 --- /dev/null +++ b/d2d_app/client/lib/tau/animation/tau.animation.js @@ -0,0 +1,4077 @@ +(function(window) { +(!window.tau) && (window.tau = {}); +var ns = window.tau.animation = {}; +(function(window, ns) { + ( function () { + + var lastTime = 0; + var vendors = [ 'ms', 'moz', 'webkit', 'o' ]; + + for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++ x ) { + + window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ]; + window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ]; + + } + + if ( window.requestAnimationFrame === undefined ) { + + window.requestAnimationFrame = function ( callback ) { + + var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ); + var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall ); + lastTime = currTime + timeToCall; + return id; + + }; + + } + + window.cancelAnimationFrame = window.cancelAnimationFrame || function ( id ) { window.clearTimeout( id ) }; + + }() ); + + (function init(window, ns) { + window.Uint8Array.prototype.setValue = function() { + for (var i = 0, len = this.length; i < len; i++) { + if (arguments[i] === undefined) { + return; + } else { + this[i] = arguments[i]; + } + } + + }; + + /** + * Gets time based on window time system + * @method getTime + * @return {Object} + * @member ns + * @static + */ + ns.getTime = (function() { + if (window.performance) { + if (window.performance.now) { + return function() { + return window.performance.now() + }; + } else { + if (window.performance.webkitNow) { + return function() { + return window.performance.webkitNow() + }; + } else { + return function() { + return new Date().getTime() + }; + } + } + } else { + return function() { + return new Date().getTime() + }; + } + })(); + + + + })(window, ns); + + + var base = { + + /** + * Enum value for type of animation + * @variable ENUM + * @member ns.base + * @private + */ + ENUM: { + NODETYPE: { + GROUP: 1, + ANIMATION: 2 + }, + GROUPTYPE: { + SEQUENCE: 4, + PARALLEL: 8 + } + }, + + /** + * Calls given function every element of array + * @method forEach + * @param {Object} a + * @param {Function} f + * @return {Object} + * @member ns.base + * @public + */ + forEach: function(a, f) { + for (var i = 0, il = (a && a.length); i < il; i++) { + var o = a[i]; + f(o, i); + } + }, + + /** + * Returns copied object from the source + * @method copy + * @param {Object} src + * @param {Object} dst + * @return {Object} + * @member ns.base + * @private + */ + copy: function(src, dst) { + dst = dst || {}; + + for (var key in src) { + if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') { + dst[key] = src[key]; +// if(typeof(src.length) !== 'undefined') { +// this.copy(src[key], dst[key]); +// } else { +// dst[key] = src[key]; +// } + } + } + + return dst; + }, + + /** + * Returns copied array from the source + * @method arrayCopy + * @param {Object} src + * @param {Object} dst + * @return {Object} + * @member ns.base + * @private + */ + arrayCopy: function(src, dst) { + var i, l = src.length; + + if (l !== undefined) { + if (dst === undefined) { + if (src instanceof Uint8Array) { + dst = new Uint8Array(l) + } else { + dst = []; + } + } + + for (i = 0; i < l; i++) { + if(typeof src[i] !== 'string' && src[i].length !== undefined) { + dst[i] = ns.base.arrayCopy(src[i]); + } else { + dst[i] = src[i]; + } + } + + } else { + dst = src; + } + + return dst; + }, + + /** + * Returns copied object from the source. DeepCopy checks all type of property in source such as object, string, number, and so on. + * @method deepCopy + * @param {Object} src + * @param {Object} dst + * @return {Object} + * @member ns.base + * @private + */ + deepCopy: function(src, dst, filter) { + if (typeof(src) == 'object') { + dst = dst || {}; + if (typeof(src.length) != 'undefined') { + if (src instanceof Array) { + dst = new Array(); + } else if (src instanceof Uint8Array) { + dst = new Uint8Array(src.length); + } + } + + for (var objInd in src) { + if (typeof(src[objInd]) == 'object') { + dst[objInd] = this.deepCopy(src[objInd]); + } else if (typeof(src[objInd]) == 'string') { + dst[objInd] = src[objInd]; + } else if (typeof(src[objInd]) == 'number') { + dst[objInd] = src[objInd]; + } else if (typeof(src[objInd]) == 'boolean') { + ((src[objInd] == true) ? dst[objInd] = true : dst[objInd] = false); + } + } + } else { + dst = src; + } + return dst; + }, + + /** + * Returns SingleTon object. This function provide usage of SingleTon pattern. + * @method singleTon + * @param {Object} SingletonObject + * @return {Object} + * @member ns.base + * @private + */ + singleTon: function(SingletonObject) { + var _singleton = {}; + + _singleton.getInstance = function() { + if (this._singleton === undefined) { + this._singleton = new SingletonObject; + } + return this._singleton; + }; + + return _singleton; + }, + + /** + * Returns true or false based on whether the type of parameter is number or not. + * @method isNumber + * @param {Number} n + * @return {Boolean} + * @member ns.base + * @public + */ + isNumber: function(n) { + return (typeof n === 'number') + }, + + /** + * Returns true or false based on whether the type of parameter is function or not. + * @method isFunction + * @param {Number} value + * @return {Boolean} + * @member ns.base + * @public + */ + isFunction: function(value) { + return (typeof value === 'function'); + }, + + /** + * Returns true or false based on whether the parameter is object or not. + * @method isObject + * @param {Number} value + * @return {Boolean} + * @member ns.base + * @public + */ + isObject: function(value) { + return (value instanceof Object); + }, + + /** + * Returns true or false based on whether the parameter is array or not. + * @method isArray + * @param {Number} value + * @return {Boolean} + * @member ns.base + * @public + */ + isArray: function(value) { + return (value instanceof Array); + }, + + // TODO: deprecated - use ns.$ + selector: function(str) { + var s = str.slice(0, 1), + c = str.slice(1), result; + + if(s === '.') { + result = document.getElementsByClassName(c); + } else if(s === '#') { + result = document.getElementById(c); + } + return result; + } + }; + + base.WeakMap = function() { + // private references holders + this.keys = []; + this.values = []; + this.i = 0; + }; + + // WeakMap#delete(key:void*):void + base.WeakMap.prototype.del = function(key) { + if (this.has(key)) { + this.keys.splice(this.i, 1); + this.values.splice(this.i, 1); + } + return -1 < this.i; + }; + + base.WeakMap.prototype.get = function(key, d3fault) { + return this.has(key) ? this.values[this.i] : d3fault; + }; + + base.WeakMap.prototype.has = function(key) { + if (key !== Object(key)) + throw new TypeError("not a non-null object"); + this.i = Array.prototype.indexOf.call(this.keys, key); + return -1 < this.i; + }; + + base.WeakMap.prototype.set = function(key, value) { + this.has(key) ? this.values[this.i] = value : this.values[this.keys.push(key) - 1] = value; + }; + + base.WeakMap.prototype.getKey = function() { + return this.keys; + }; + + var initializing = false, fnTest = /xyz/.test(function() { + xyz; + }) ? /\b_super\b/ : /.*/; + + // The base Class implementation (does nothing) + base.Class = function() { + }; + + // Create a new Class that inherits from this class + base.Class.extend = function(prop) { + var _super = this.prototype; + var _static = prop.static; + // Instantiate a base class (but only create the instance, + // don't run the init constructor) + initializing = true; + var prototype = new this(); + initializing = false; + + // Copy the properties over onto the new prototype + for (var name in prop) { + if (name !== 'static') { + // Check if we're overwriting an existing function + prototype[name] = typeof prop[name] == "function" && + typeof _super[name] == "function" && fnTest.test(prop[name]) ? + (function(name, fn) { + return function() { + var tmp = this._super; + + // Add a new ._super() method that is the same method + // but on the super-class + this._super = _super[name]; + + // The method only need to be bound temporarily, so we + // remove it when we're done executing + var ret = fn.apply(this, arguments); + this._super = tmp; + + return ret; + }; + })(name, prop[name]) : + prop[name]; + } + + } + + // The dummy class constructor + function Class() { + // All construction is actually done in the init method + if (!initializing && this._init) + return this._init.apply(this, arguments); + } + + // Populate our constructed prototype object + Class.prototype = prototype; + + // Enforce the constructor to be what we expect + Class.prototype.constructor = Class; + + // And make this class extendable + Class.extend = arguments.callee; + + if (_static) { + for (var p in _static) { + if (_static.hasOwnProperty(p)) { + Class[p] = _static[p]; + } + } + } + + return Class; + }; + + ns.base = base; + +})(window, ns); + + + + + + + + +(function(window, ns) { + 'use strict'; + + var Ticker = ns.base.Class.extend({ + _init: function() { + + this.now = ns.getTime; + this._frameId = null; // requeatAnimatoinFrame ID + + this.animators = []; + this.animatorIdx = 0; + }, + + /** + * On requestAnimationFrame with tick. + * @method tickOn + * @member ns.Ticker + * @private + */ + tickOn: function() { + var self = this; + + (function loop() { + self._frameId = window.requestAnimationFrame(loop); + var i, + time = ns.getTime(); + + for(i = 0; i < self.animatorIdx; i++) { + self.animators[i].tick(time); + } + })(); + }, + + /** + * Off requestAnimationFrame by cancelAnimationFrame. + * @method tickOn + * @member ns.Ticker + * @private + */ + tickOff: function() { + if(this._frameId) { + window.cancelAnimationFrame(this._frameId); + this._frameId = null; + } + }, + + /** + * Triggers Ticker's status by on + * @event __on + * @member ns.Ticker + * @private + */ + __on : function(e) { + if(this.animators.indexOf(e) < 0) { // TODO : change map ? + //this.animators.push(e); + this.animators[this.animatorIdx] = e; + this.animatorIdx++; + + if(this._frameId === null) { + this.tickOn(); + } + } + }, + + /** + * Triggers Ticker's status by off + * @event __off + * @member ns.Ticker + * @private + */ + __off : function(e) { + var idx = this.animators.indexOf(e); + if(idx >= 0) { + + this.animators.splice(idx, 1); + this.animatorIdx--; + + if(this.animatorIdx === 0) { + this.tickOff(); + } + } + } + }); + + /* + * Ticks with requestAnimationFrame + */ + ns.Ticker = ns.base.singleTon(Ticker); +})(window, ns); + +(function(window, ns) { + 'use strict'; // jshint ignore:line + + var p; + function Ease() { + this.regExpCubicBezier = /cubic-bezier\s*\(\s*([\d\.]+)\s*,\s*([\d\.]+)\s*,\s*([\d\.]+)\s*,\s*([\d\.]+)\s*\)/; + } + + function cubicBezier(x1, y1, x2, y2) { + return function(t) { + var rp = 1 - t, rp3 = 3 * rp, p2 = t * t, p3 = p2 * t, a1 = rp3 * t * rp, a2 = rp3 * p2; + return a1 * y1 + a2 * y2 + p3; + }; + } + + function calcBounceOut(t) { + if (t < 1 / 2.75) { + return (7.5625 * t * t); + } else if (t < 2 / 2.75) { + return (7.5625 * (t -= 1.5 / 2.75) * t + 0.75); + } else if (t < 2.5 / 2.75) { + return (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375); + } else { + return (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375); + } + } + + p = Ease.prototype; + p.ease = cubicBezier(0.25, 0.1, 0.25, 1); + + p.easeOut = cubicBezier(0, 0, 0.58, 1); + + p.easeInOut = cubicBezier(0.42, 0, 0.58, 1); + + p.easeIn = cubicBezier(0.42, 0, 1, 1); + + p.sineIn = cubicBezier(0.47, 0, 0.745, 0.715); + + p.sineOut = cubicBezier(0.39, 0.575, 0.565, 1); + + p.sineInOut = cubicBezier(0.445, 0.05, 0.55, 0.95); + + p.expoIn = cubicBezier(0.95, 0.05, 0.795, 0.035); + + p.expoOut = cubicBezier(0.19, 1, 0.22, 1); + + p.expoInOut = cubicBezier(1, 0, 0, 1); + + p.circIn = cubicBezier(0.6, 0.04, 0.98, 0.335); + + p.circOut = cubicBezier(0.075, 0.82, 0.165, 1); + + p.circInOut = cubicBezier(0.785, 0.135, 0.15, 0.86); + + p.backIn = cubicBezier(0.6, -0.28, 0.735, 0.045); + + p.backOut = cubicBezier(0.175, 0.885, 0.32, 1.275); + + p.backInOut = cubicBezier(0.68, -0.55, 0.265, 1.55); + + p.zoomInDown = cubicBezier(0.55, 0.055, 0.675, 0.19); + + p.bounce1 = cubicBezier(0.215, 0.610, 0.355, 1.000); + p.bounce2 = cubicBezier(0.755, 0.050, 0.855, 0.060); + + // http://gizma.com/easing/ + p.linear = function(t) { + return t; + }; + + p.cubicIn = function(t) { + return t * t * t; + }; + + p.cubicOut = function(t) { + return (--t) * t * t + 1; + }; + + p.cubicInOut = function(t) { + return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; + }; + + p.quadIn = function(t) { + return t * t; + }; + + p.quadOut = function(t) { + return t * (2 - t); + }; + + p.quadInOut = function(t) { + return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t; + }; + + p.quartIn = function(t) { + return t * t * t * t; + }; + + p.quartOut = function(t) { + return 1 - (--t) * t * t * t; + }; + + p.quartInOut = function(t) { + return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t; + }; + + p.quintIn = function(t) { + return t * t * t * t * t; + }; + + p.quintOut = function(t) { + return 1 + (--t) * t * t * t * t; + }; + + p.quintInOut = function(t) { + return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t; + }; + + p.bounceOut = function(t) { + return calcBounceOut(t); + }; + + p.bounceIn = function(t) { + return 1 - Ease.prototype.bounceOut(1 - t); + }; + + p.bounceInOut = function(t) { + if (t < 0.5) { + return Ease.prototype.bounceIn(t * 2) * 0.5; + } + return Ease.prototype.bounceOut(t * 2 - 1) * 0.5 + 0.5; + }; + + var pi2 = Math.PI * 2; + var defaultS = 0.3 / pi2 * Math.asin(1); + + p.elasticIn = function(t) { + if (t === 0 || t === 1) { + return t; + } + return -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - defaultS) * pi2 / 0.3)); + }; + + p.elasticOut = function(t) { + if (t === 0 || t === 1) { + return t; + } + return (Math.pow(2, -10 * t) * Math.sin((t - defaultS) * pi2 / 0.3) + 1); + }; + + p.elasticInOut = function(t) { + if ((t *= 2) < 1) { + return -0.5 * (Math.pow(2, 10 * (t -= 1)) * Math.sin((t - defaultS) * pi2 / 0.3)); + } + return Math.pow(2, -10 * (t -= 1)) * Math.sin((t - defaultS) * pi2 / 0.3) * 0.5 + 1; + }; + /* + * Provides ease functions + */ + ns.Ease = ns.base.singleTon(Ease); +})(window, ns); +/* + * # Tween Animator + * + * Provides Tween and animate javascript properties. + * + * @example + * var box = document.getElementById('box'); + * var tween = new ns.Tween({width: 100, height:100}, {width: 200, height: 250}, { + * duration: 1000, + * onUpdate: function() { + * box.style.width = this.width + 'px'; + * box.style.height = this.height + 'px'; + * } + * }); + * tween.play() + * + * @class ns.TweenAnimator + */ +(function(window, ns) { + 'use strict'; + + var Ticker = ns.Ticker.getInstance(), + Ease = ns.Ease.getInstance(), + // enum + STATE = { + STOP: 'stop', + PAUSE: 'pause', + RUN: 'running' + }, + DIRECTION = { + FORWARD: true, + REVERSE: false + }; + + var createTweens = function() { + var idx = 0, + length = 0, + tweens = []; + + return { + add: function(tween) { + tweens[length] = tween; + length++; + }, + + next: function() { + + if (idx < length) { + idx++; + return tweens[idx - 1]; + } else { + return false; + } + }, + + cur: function() { + return idx; + }, + + rewind: function() { + idx = 0; + }, + + get: function(i) { + return (i === undefined ? tweens : tweens[i]); + }, + + length: function() { + return length; + }, + + hasNext: function() { + return idx < length; + }, + + clear: function() { + if (length !== 0 && idx <= length) { + tweens.splice(0, idx) + } + idx = 0; + length = tweens.length; + }, + + allClear: function() { + tweens = []; + idx = length = 0; + } + + } + }; + + var createEvent = function() { + var listeners = [], + length = 0; + + return { + on: function(f) { + listeners[length] = f; + length++; + }, + + onFront: function(f) { + listeners.unshift(f); + length++; + }, + + emit: function() { + for (var i = 0; i < length; i++) { + listeners[i].apply(null, arguments); + } + }, + + remove: function(f) { + for (var i = 0; i < length; i++) { + if (listeners[i] === f) { + listeners[i].splice(i, 1); + length--; + } + } + }, + + getLength: function() { + return length; + }, + + removeAll: function() { + listeners = []; + length = 0; + } + } + }; + + var TweenAnimator = ns.base.Class.extend({ + _init: function(fromTo, option) { + + this.tweenQueue = createTweens(); + this.tweenInfo = null; + + // state + this._direction = DIRECTION.FORWARD; + this._state = STATE.STOP; + this._isTick = false; + this.isTweenInfo = false; + + fromTo && this.add(fromTo, option); + + // time value + this._startTime = this._lastTime = this._playTime = this._previousTime = 0; + this._totalTime = this._duration + this._delay; + //this._progress = 0; + + // check to change direction + this._changedDirection = false; + + // tween queue cache + this._isCache = false; // don't save tween object + }, + + /** + * Called by Ticker every frame + * @method tick + * @param {number} tick time + * @member ns.TweenAnimator + * @private + */ + tick: function(delta) { + + if (this._state === STATE.RUN) { + var now = delta, + runTime = now - this._playTime; + + this._previousTime = now; + + if (runTime < 0) { + return; + } else if (runTime <= this._duration) { + this.tweenInfo.progress = runTime / (this._duration || 1); + + this._update(); + } else { + + if (this.tweenInfo.progress !== 1) { + this.tweenInfo.progress = 1; + this._update(); + } + if (now >= this._lastTime) { + this._complete(); + } + } + } + }, + + /** + * Start tween animation + * @method play + * @member ns.TweenAnimator + * @public + */ + play: function() { + if (this._state === STATE.RUN) { + return; + } + + if (this._state === STATE.PAUSE) { + if (this._direction !== DIRECTION.FORWARD) { + this._direction = DIRECTION.FORWARD; + this._changedDirection = true; + } + this.resume(); + + } else { + this._direction = DIRECTION.FORWARD; + this._play(); + } + }, + + /** + * Start tween animation to the reverse direction. + * @method reverse + * @member ns.TweenAnimator + * @public + */ + reverse: function() { + if (this._state === STATE.RUN) { + return; + } + + if (this._state === STATE.PAUSE) { + if (this._direction !== DIRECTION.REVERSE) { + this._direction = DIRECTION.REVERSE; + this._changedDirection = true; + } + this.resume(); + + } else { + this._direction = DIRECTION.REVERSE; + this._play(); + } + }, + + /** + * Stop tween animation. + * @method stop + * @member ns.TweenAnimator + * @public + */ + stop: function() { + if (this._state !== STATE.STOP) { + this._stopTween(); + this.tweenQueue.allClear(); + // TODO : call complete callback? + } + }, + + /** + * Pause tween animation. + * @method pause + * @member ns.TweenAnimator + * @public + */ + pause: function() { + if (this._state === STATE.RUN) { + this._state = STATE.PAUSE; + } + + }, + + /** + * Resume tween animation if it is paused. + * @method resume + * @param {string} direction + * @member ns.TweenAnimator + * @public + */ + resume: function(direction) { + var cur = ns.getTime(); + + if (this._state === STATE.PAUSE) { + + if (this._changedDirection || (direction !== undefined && direction !== this._direction)) { + if (direction !== undefined) { + this._direction = direction; + } + this._lastTime = cur + this._previousTime - this._playTime; + this._playTime = this._lastTime - this._duration; + this._startTime = this._playTime - this._delay; + + this._changedDirection = false; + } else { + var elapsedTime = cur - this._previousTime; + this._startTime += elapsedTime; + this._playTime += elapsedTime; + this._lastTime += elapsedTime; + } + + this._state = STATE.RUN; + } + + }, + + /** + * Jump to a specific time + * @method seek + * @param {number} specific time + * @member ns.TweenAnimator + * @public + */ + seek: function(n) { + var seekTime = n * this._totalTime - this._delay; + if (seekTime >= 0) { + this._update(seekTime / this._duration); + } + }, + + /** + * Get value of seek time + * @method getSeek + * @param {number} seek time + * @return {number} value + * @member ns.TweenAnimator + * @private + */ + getSeek: function(p, type) { + var i, name, l, p, + n = this.tweenInfo.name, + t = this.tweenInfo.to, + f = this.tweenInfo.from; + + if (type) { + p = p * this._totalTime - this._delay + } + + for (i = 0; name = n[i]; i++) { + + if (this.cur[name] && (l = this.cur[name].length)) { + (this.cur[name] === undefined) && (this.cur[name] = []); + this._calculateTween(this.cur[name], t[name], f[name], p); + + } else { + this.cur[name] = (t[name] - f[name]) * this._ease(p) + f[name]; + } + + } + + return this.cur; + }, + + /** + * Set start time of tween + * @method setStartTime + * @param {number} start time + * @member ns.TweenAnimator + * @private + */ + setStartTime: function(time) { + this._startTime = time; + //this._playTime = this._startTime + (this._direction ? this._delay : 0); + //this._lastTime = this._playTime + this._duration + (this._direction ? 0 : this._delay); + }, + + /** + * Replay tween animation + * @method replay + * @member ns.TweenAnimator + * @private + */ + replay: function() { + this._update(0); + this._start(); + }, + + /** + * Set duration of tween + * @method duration + * @param {number} + * @member ns.TweenAnimator + * @private + */ + duration: function(n) { + this._duration = ns.base.isNumber(n) ? n : 1000; + }, + + /** + * Set delay of tween + * @method delay + * @param {number} + * @member ns.TweenAnimator + * @private + */ + delay: function(n) { + this._delay = ns.base.isNumber(n) ? n : 0; + }, + + /** + * Set ease of tween + * @method ease + * @param {string} + * @member ns.TweenAnimator + * @private + */ + ease: function(f) { + this._ease = ns.base.isFunction(Ease[f]) ? Ease[f] : Ease.linear; + }, + + /** + * Set loop of tween + * @method loop + * @param {number} + * @member ns.TweenAnimator + * @private + */ + loop: function(n) { + this._loop = ns.base.isNumber(n) ? n : 1; + }, + + /** + * Add tween object + * @method add + * @param {object} fromTo from and to value object + * @param {object} option value object including duration, delay, ease ans so on. + * @member ns.TweenAnimator + * @public + */ + add: function(fromTo, option) { + var tween; + + if (option === undefined) { + tween = fromTo; + tween.startCallback = createEvent(); + tween.completeCallback = createEvent(); + tween.progress = 0; + } else { + tween = { + fromTo: {}, + name: [], + progress: 0, + startCallback: createEvent(), + completeCallback: createEvent() + }; + + tween.option = option; + } + + tween.option.onStart && tween.startCallback.on(tween.option.onStart); + tween.option.onComplete && tween.completeCallback.on(tween.option.onComplete); + + this.tweenQueue.add(tween); + + if (this.tweenQueue.length() === 1) { + this.tweenQueue.next(); + this.initTween(tween); + this.isTweenInfo = true; + } + + return tween; + }, + + /** + * Shift to next tween object. + * @method nextTween + * @return {object | boolean} tween object or false if not. + * @member ns.TweenAnimator + * @private + */ + + setRender: function(f) { + this.render = f; + }, + + setUpdateTarget: function(target) { + this.cur = target; + }, + + getState: function() { + return this._state; + }, + + getCurrentTweenInfo: function() { + return this.tweenInfo; + }, + + nextTweenInfo: function() { + return this.tweenQueue.next(); + }, + + getLastTweenInfo: function() { + return this.tweenQueue.get(this.tweenQueue.length() - 1); + }, + + getFirstTweenInfo: function() { + return this.tweenQueue.get(0); + }, + /** + * Initialize cur tween object. + * @method initTween + * @param {object} tweenInfo object + * @member ns.TweenAnimator + * @private + */ + initTween: function(tweenInfo) { + var option = tweenInfo.option; + + this.tweenInfo = tweenInfo; + this.cur = (this.cur !== undefined) ? this.cur : (option._cur !== undefined) ? option._cur : {}; + + this.option = option; + + // user event + this._onUpdate = option.onUpdate; // only one update callback exists because it affect performance. + + // tween option value + if (ns.base.isObject(option)) { + this.duration(option.duration); + this.ease(option.ease); + this.delay(option.delay); + this.loop(option.loop); + + this._reverseDelay = option.reverseDelay || 0; + + } else { + this._duration = 1000; + this._delay = 0; + this._loop = 1; + this._ease = Ease.linear; + this._reverseDelay = 0; + } + this._loopCnt = this._loop; + + }, + + tweenQueueCache: function(flag) { + (typeof flag === 'boolean') && (this._isCache = flag); + }, + + /** + * If state is stop, start tween. or If it is pause, resume tween. + * @method _play + * @member ns.TweenAnimator + * @private + */ + _play: function() { + if (this._state === STATE.PAUSE) { + this.resume(); + } else if (this._state === STATE.STOP) { + this._start(); + } + }, + + /** + * Calculate start, play and last time. And start tick. + * @method _start + * @member ns.TweenAnimator + * @private + */ + _start: function() { + this._state = STATE.RUN; + + this._startTime = this._startTime || ns.getTime(); + this._playTime = this._startTime + (this._direction ? this._delay : 0); + this._lastTime = this._playTime + this._duration + (this._direction ? 0 : this._delay) + this._reverseDelay; + + //this._onStart && this._onStart(); + this.tweenInfo.startCallback.emit(); + + if (!this._isTick) { + Ticker.__on(this); + this._isTick = true; + } + }, + + /** + * Update tween value every frame. + * @method _update + * @param {number} progress + * @member ns.TweenAnimator + * @private + */ + _update: function(e) { + var i, name, l, + n = this.tweenInfo.name, + ft = this.tweenInfo.fromTo; + + this.tweenInfo.progress = (e !== undefined) ? + e : (this._direction === DIRECTION.REVERSE ? 1 - this.tweenInfo.progress : this.tweenInfo.progress); + + // render + for (i = 0; name = n[i]; i++) { + if (ft[name][0] && (l = ft[name][0].length)) { + (this.cur[name] === undefined) && (this.cur[name] = []); + this._calculateTween(this.cur[name], ft[name][0], ft[name][1]); + + } else { + this.cur[name] = (ft[name][1] - ft[name][0]) * this._ease(this.tweenInfo.progress) + ft[name][0]; + } + } + + this.render && this.render.call(this.cur, this.tweenInfo); + this._onUpdate && this._onUpdate.call(this.cur, this.tweenInfo); + }, + + /** + * Calculate tween value. + * @method _calculateTween + * @param {number} current value + * @param {number} from value + * @param {number} to value + * @param {number} progress + * @member ns.TweenAnimator + * @private + */ + _calculateTween: function(c, f, t, p) { + var i, l; + (p === undefined) && (p = this.tweenInfo.progress); + + for (i = 0, l = t.length; i < l; i++) { + if (typeof t[i] === 'number') { + c[i] = (t[i] - f[i]) * this._ease(p) + f[i]; + } else if (typeof t[i] === 'string') { + c[i] = t[i]; + } else { + (c[i] === undefined) && (c[i] = []); + this._calculateTween(c[i], f[i], t[i]); + } + } + }, + + /** + * If tween completed, call this function. + * @method _complete + * @member ns.TweenAnimator + * @private + */ + _complete: function() { + var nextTween; + this.setStartTime(null); + this.isTweenInfo = false; + this.tweenInfo.completeCallback.emit(); + + // loop check + if (--this._loopCnt > 0) { + this.replay(); + } else { + // search next tweenInfo + if (!this.isTweenInfo && (nextTween = this.tweenQueue.next())) { + this.initTween(nextTween); + + if (!this._isCache) { + this.tweenQueue.clear(); + } + + this._start(); + } else { + if (this.isTweenInfo) { + this._start(); + } else { + // finish tween + this._stopTween(); + + if (this.option._stackTweensFlag) { + this.tweenQueue.rewind(); + nextTween = this.tweenQueue.next(); + this.initTween(nextTween); + } else { + this.tweenQueue.allClear(); + } + } + + } + } + + }, + + /** + * Stop tween object and stop tick. + * @method _stopTween + * @member ns.TweenAnimator + * @private + */ + _stopTween: function() { + this._state = STATE.STOP; + this._startTime = null; + Ticker.__off(this); + this._isTick = false; + } + + }); + + ns.TweenAnimator = ns.Tween = TweenAnimator; +})(window, ns); +(function(window, ns, base) { + 'use strict'; + + var Transform = ns.base.Class.extend({ + _init: function() { + this.init(); + }, + + /** + * Initialize transform values + * @method init + * @member ns.Transform.init + * @private + */ + init: function() { + this.translateX = 0; + this.translateY = 0; + this.translateZ = 0; + + this.rotateX = 0; + this.rotateY = 0; + this.rotateZ = 0; + + this.skewX = 0; + this.skewY = 0; + + this.scaleX = 1; + this.scaleY = 1; + }, + + /** + * Copy transform values + * @method copy + * @param {object} source transform value + * @member ns.Transform.copy + * @private + */ + copy: function(t) { + this.translateX = t.translateX; + this.translateY = t.translateY; + this.translateZ = t.translateZ; + + this.rotateX = t.rotateX; + this.rotateY = t.rotateY; + this.rotateZ = t.rotateZ; + + this.skewX = t.skewX; + this.skewY = t.skewY; + + this.scaleX = t.scaleX; + this.scaleY = t.scaleY; + }, + + /** + * Set transform array values + * @method set + * @param {array} source transform array value + * @member ns.Transform.set + * @private + */ + set: function(t) { + if(t instanceof Array) { + // translate, rotate, scale, skew + this.translateX = base.isNumber(t[0]) ? t[0] : 0; + this.translateY = base.isNumber(t[1]) ? t[1] : 0; + this.translateZ = base.isNumber(t[2]) ? t[2] : 0; + + this.rotateX = base.isNumber(t[3]) ? t[3] : 0; + this.rotateY = base.isNumber(t[4]) ? t[4] : 0; + this.rotateZ = base.isNumber(t[5]) ? t[5] : 0; + + this.scaleX = base.isNumber(t[6]) ? t[6] : 1; + this.scaleY = base.isNumber(t[7]) ? t[7] : 1; + + this.skewX = base.isNumber(t[8]) ? t[8] : 0; + this.skewY = base.isNumber(t[9]) ? t[9] : 0; + } + } + }); + + /* + * Sets or Initialize webkitTransform property + */ + ns.Transform = Transform; + +})(window, ns, ns.base); + +(function(window, ns, base) { + 'use strict'; + + var colorTable = { + aqua: new Uint8Array([0, 255, 255]), + lime: new Uint8Array([0, 255, 0]), + silver: new Uint8Array([192, 192, 192]), + black: new Uint8Array([0, 0, 0]), + maroon: new Uint8Array([128, 0, 0]), + teal: new Uint8Array([0, 128, 128]), + blue: new Uint8Array([0, 0, 255]), + navy: new Uint8Array([0, 0, 128]), + white: new Uint8Array([255, 255, 255]), + fuchsia: new Uint8Array([255, 0, 255]), + olive: new Uint8Array([128, 128, 0]), + yellow: new Uint8Array([255, 255, 0]), + orange: new Uint8Array([255, 165, 0]), + gray: new Uint8Array([128, 128, 128]), + purple: new Uint8Array([128, 0, 128]), + green: new Uint8Array([0, 128, 0]), + red: new Uint8Array([255, 0, 0]), + pink: new Uint8Array([255, 192, 203]), + cyan: new Uint8Array([0, 255, 255]), + transparent: new Uint8Array([255, 255, 255, 0]) + }; + + var CSSPropertyParser = base.Class.extend({ + + _init: function() { + var self = this; + + // px & unit + var pxType = ['borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', + 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', + 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', + 'width', 'height', 'top', 'left', + 'clipTop', 'clipBottom', 'clipRight', 'clipLeft', + 'fontSize', 'lineHeight']; + pxType.forEach(function(type) { + self[type] = self._unit.bind(self); + }); + + var backgroundType = ['backgroundPosition', 'backgroundSize']; + backgroundType.forEach(function(type) { + self[type] = self._arrayUnit.bind(self); + + }); + + // border + var borderType = ['border', 'borderTop', 'borderRight', 'borderLeft', 'borderBottom']; + borderType.forEach(function(type) { + self[type] = function _border(str) { + var result = {}, temp; + + temp = self._blank(str); + + result[type + 'Width'] = temp[0]; + result[type + 'Style'] = temp[1] === 'none' ? 'solid' : temp[1]; // TODO: 유효성 체크 + result[type + 'Color'] = temp[2]; + + return result; + }; + }); + + // color + var colorType = ['backgroundColor', 'color', + 'borderColor', 'borderTopColor', 'borderRightColor', 'borderLeftColor', 'borderBottomColor']; + + colorType.forEach(function(type) { + self[type] = self._color; + }); + + //margin & padding + var blankType = ['margin', 'padding']; + blankType.forEach(function(type) { + self[type] = function _blank(str) { + var temp = self._blank(str), result = {}; + + if (temp.length === 4) { + result[type + 'Top'] = temp[0]; + result[type + 'Right'] = temp[1]; + result[type + 'Bottom'] = temp[2]; + result[type + 'Left'] = temp[3]; + } else if (temp.length === 3) { + result[type + 'Top'] = temp[0]; + result[type + 'Right'] = temp[1]; + result[type + 'Bottom'] = temp[2]; + result[type + 'Left'] = temp[1]; + } else if (temp.length === 2) { + result[type + 'Top'] = temp[0]; + result[type + 'Right'] = temp[1]; + result[type + 'Bottom'] = temp[0]; + result[type + 'Left'] = temp[1]; + } else if (temp.length === 1) { + result[type + 'Top'] = temp[0]; + result[type + 'Right'] = temp[0]; + result[type + 'Bottom'] = temp[0]; + result[type + 'Left'] = temp[0]; + } + + return result; + } + }); + + //var unitWithString = ['lineHeight', 'fontSize']; + //unitWithString.forEach(function(type){ + // self[type] = function _unitString(str){ + // var result; + // + // result = self._unit(str); + // + // if(isNaN(result.value)) { + // result = str; + // } + // + // return result; + // } + //}); + + var shadowType = ['boxShadow', 'textShadow']; + shadowType.forEach(function(type) { + self[type] = function _shadowString(str) { + + var i, j, length, string, result = [], color, rgbArray = [], len, rgbIdx = 0, + rgbExp = /rgb\([0-9]+[\, |\s]+[0-9]+[\, |\s]+[0-9]+\)/g, shadowLength; + + rgbArray = str.match(rgbExp) || []; + str = str.replace(rgbExp, 'rgb'); + + str = str.split(','); + + for (i = 0, length = str.length; i < length; i++) { + + + if (str[i].match('rgb') && rgbArray[rgbIdx]) { + str[i] = str[i].replace('rgb', rgbArray[rgbIdx]); + rgbIdx++; + } + + + str[i] = self._blank(str[i]); + shadowLength = str[i].length - 1; + // search color + + if ((color = self._color(str[i][0]))) { + str[i].splice(0, 1); + str[i].push(color); + } else { + color = self._color(str[i][shadowLength]); + } + + for (j = 0; j < shadowLength; j++) { + str[i][j] = self._unit(str[i][j]); + } + str[i][j] = color; + } + + + return str; + } + }); + + }, + + opacity: function(v) { + return parseFloat(v); + }, + + clip: function(v) { + var text = v.replace(/\(|\)|,/g, ' ').trim().split(/\s+/g); + + var result = []; + result[0] = text[0]; + + for (var i = 1; i <= 4; i++) { + result[i] = this._unit(text[i]); + } + return result; + }, + + webkitClipPath: function(v) { + var result = [], i, len, + text = v.replace(/\(|\)|,/g, ' ').trim().split(/\s+/g); + + result.push(text[0]); + for (i = 1, len = text.length; i < len; i++) { + result.push(this._unit(text[i])); + } + + return result; + }, + + backgroundImage: function(v) { + return v.replace(/url\(|\)$/ig, ""); + }, + + _arrayUnit: function(v) { + var i, l, result = v.trim().split(' '); + + for (i = 0, l = result.length; i < l; i++) { + result[i] = this._unit(result[i]); + } + return result; + }, + + _unit: function(str) { + if (typeof str === 'string') { + return { + number: this._getFloat(str), + unit: (this._getChar(str) || 'px') + } + } else { + return { + number: str, + unit: 'px' + }; + } + }, + + _color: function(colorValue) { + //console.log(colorValue); + var first, second, third, rgb, length, i, string, result; + if (colorValue === undefined || colorValue === null) { + console.log('invalid color'); + return false; + } + + if (colorTable[colorValue]) { //for string color value such as 'red' + result = colorTable[colorValue]; + } else if (colorValue instanceof Array || colorValue instanceof Uint8Array) { + result = new Uint8Array(colorValue); + } else { + string = colorValue.toLowerCase(); + string = string.trim(); + if (string.charAt(0) === 'r' && string.charAt(1) === 'g' && string.charAt(2) === 'b') { + if (string.charAt(3) === 'a') { + rgb = string.replace(/rgba\(/g, '').replace(/\)/g, '').replace(/(\s*)/g, '').replace(/\,/g, ' ').split(' '); + for (i = 0, length = rgb.length - 1; i < length; i++) { + rgb[i] = parseInt(rgb[i]); + } + rgb[length] = parseFloat(rgb[length]); + } else { + rgb = string.replace(/rgb\(/g, '').replace(/\)/g, '').replace(/(\s*)/g, '').replace(/\,/g, ' ').split(' '); + for (i = 0, length = rgb.length; i < length; i++) { + rgb[i] = parseInt(rgb[i]); + } + } + result = new Uint8Array(rgb); + + } else if (string.charAt(0) === '#') { //for '#XXX' or '#XXXXXX' + if (string.length === 4) { + first = string.charAt(1); + second = string.charAt(2); + third = string.charAt(3); + string = "#" + first + first + second + second + third + third; + } + + string = parseInt(string.substr(1), 16); // remove '#' + result = new Uint8Array(3); + result.setValue(string >> 16, (string >> 8) & 255, string & 255); + } else { + return false; +// console.log(colorValue); + } + } + return result; + }, + + _getChar: function(arg) { + var charArr = arg.match(/[^0-9.-]/g); + var string = ''; + + if (charArr !== null) { + string = charArr.join(''); + } + + string.replace(/\, /g, ''); + + return string; + }, + + _getNum: function(arg) { + return parseInt(arg.match(/^[-]?\d+/g), 10); + }, + + _getFloat: function(arg) { + return parseFloat(arg.match(/^[+-]?\d*(\.?\d*)/g)); + }, + + _blank: function(str) { + return str.trim().replace(/\, /g, ',').split(' '); + } + }); + + /* + * Parses css properties. + */ + ns.CSSPropertyParser = base.singleTon(CSSPropertyParser); + +})(window, ns, ns.base); +(function(window, ns, base) { + 'use strict'; + + var CssStringCreator = base.Class.extend({ + + _init: function() { + this.createColor(); + this.createBorderStyle(); + this.createBlankFunction(); + this.createUnit(); + //this.createUnitWithString(); + this.createShadow(); + }, + + + opacity: function(value) { + return value.opacity; + }, + + WebkitTransform: function(value) { + var string = ''; + string += value.perspective ? ('perspective(' + value.perspective + 'px) ') : ''; + string += 'translate3d(' + value.translateX + 'px, ' + value.translateY + 'px, ' + value.translateZ + 'px) '; + + string += value.rotateX ? ('rotateX(' + value.rotateX + 'deg) ') : ''; + string += value.rotateY ? ('rotateY(' + value.rotateY + 'deg) ') : ''; + string += value.rotateZ ? ('rotateZ(' + value.rotateZ + 'deg) ') : ''; + + string += (value.scaleX !== 1) ? ('scaleX(' + value.scaleX + ') ') : ''; + string += (value.scaleY !== 1) ? ('scaleY(' + value.scaleY + ') ') : ''; + + string += value.skewX ? ('skewX(' + value.skewX + 'deg) ') : ''; + string += value.skewY ? ('skewY(' + value.skewY + 'deg) ') : ''; + + return string; + }, + + createUnit: function() { + var self = this, + type = ['width', 'height', 'top', 'left'], + backgroundType = ['backgroundPosition', 'backgroundSize']; + + function _unit(v, u) { + if (u[this] === 'px') { + return Math.round(v[this]) + u[this]; + } + return v[this] + u[this]; + } + + type.forEach(function(f) { + self[f] = _unit.bind(f) + }); + + backgroundType.forEach(function(f) { + self[f] = _background.bind(f) + }); + + function _background(v, u) { + return v[this][0] + u[this][0] + ' ' + v[this][1] + u[this][1]; + } + }, + + createColor: function() { + var self = this; + var type = ['borderColor', 'borderTopColor', 'borderRightColor', 'borderLeftColor', 'borderBottomColor', + 'backgroundColor', 'color']; + type.forEach(function(f) { + self[f] = self._rgbColor(f); + }); + }, + + createBorderStyle: function() { + var self = this; + + var borderType = ['border', 'borderTop', 'borderRight', 'borderLeft', 'borderBottom']; + var borderWidthType = ['borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderLeftWidth', 'borderBottomWidth']; + var borderStyleType = ['borderStyle', 'borderTopStyle', 'borderRightStyle', 'borderLeftStyle', 'borderBottomStyle']; + + function _border(v, u) { + + var width = this + 'Width', + color = this + 'Color', + style = this + 'Style'; + //console.log(v[color]); + return v[width] + u[width] + ' ' + u[style] + ' rgb(' + + v[color][0] + ', ' + v[color][1] + ', ' + v[color][2] + ')'; + } + + function _borderWidth(v, u) { + return v[this].toFixed(2) + u[this]; + } + + borderType.forEach(function(f) { + self[f] = _border.bind(f) + }); + + borderStyleType.forEach(function(f) { + self[f] = self._direct(f); + }); + + borderWidthType.forEach(function(f) { + self[f] = _borderWidth.bind(f) + }); + }, + + createBlankFunction: function() { + var self = this; + var blank = ['margin', 'padding']; + var blankType = ['marginTop', 'marginRight', 'marginBottom', 'marginLeft', + 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', + 'lineHeight', 'fontSize']; + + blank.forEach(function(f) { + self[f] = _blank.bind(f) + }); + + function _blank(v, u) { + var top = this + 'Top', + right = this + 'Right', + bottom = this + 'Bottom', + left = this + 'Left'; +// console.log(v[top], u[top]); + return v[top] + u[top] + ' ' + v[right] + u[right] + ' ' + v[bottom] + u[bottom] + ' ' + v[left] + u[left]; + } + + blankType.forEach(function(f) { + self[f] = _blanktype.bind(f); + }); + + function _blanktype(v, u) { +// console.log(v[this], u[this]); + return v[this] + u[this]; + } + }, + +// createUnitWithString: function(){ +// var self = this, +// unitType = []; +// +// unitType.forEach(function(f){ +// self[f] = _unit.bind(f) +// }); +// +// function _unit(f) { +// return f[this][0] + f[this][1]; +// } +// }, + + createShadow: function() { + var self = this, + shadowType = ['boxShadow', 'textShadow']; + + shadowType.forEach(function(name) { + self[name] = function(v, u) { + var value = v[name], unit = u[name], i, j, shadowLen, len, str = ''; + for (i = 0, shadowLen = value.length; i < shadowLen; i++) { + + (i !== 0) && (str += ', '); + + for (j = 0, len = value[i].length - 1; j < len; j++) { + str += value[i][j] + unit[i][j] + ' '; + } + + str += 'rgb(' + value[i][j][0] + ',' + value[i][j][1] + ',' + value[i][j][2] + ') '; + + } + //console.log(str); + return str; + } + }); + }, + + //createShadow: function(){ + // var self = this, + // shadowType = ['boxShadow', 'textShadow']; + // + // shadowType.forEach(function(f){ + // self[f] = _shadow.bind(f); + // }); + // + // function _shadow(v){ + // var result = '', i = 0, j = 0, length = 0, len = 0; + // for(j = 0, length = v[this].length; j < length; j++){ + // for(i = 0, len = v[this][j].length; i < len; i++) { + // if(v[this][j][i].length === 2) { + // if(v[this][j][i][1] !== '') { + // result += (v[this][j][i][0] + v[this][j][i][1] + ' '); + // } + // + // } else if(v[this][j][i].length === 3){ + // result += 'rgb(' + (v[this][j][i][0] + ',' + v[this][j][i][1] + ',' + v[this][j][i][2] + ')'); + // } else if(v[this][j][i] === 'inset') { + // result += ' inset'; + // } + // } + // if( (length-1) > j){ + // result += ', '; + // } + // } + // return result; + // } + //}, + + + clip: function(v) { + return v.clip[0] + '(' + v.clip[1][0] + v.clip[1][1] + ' ' + v.clip[2][0] + v.clip[2][1] + + ' ' + v.clip[3][0] + v.clip[3][1] + ' ' + v.clip[4][0] + v.clip[4][1] + ')'; + + }, + +// clip: function(value, unit) { +// var v = value.clip, +// u = unit.clip; +// +// return 'rect(' + v[0] + u[0] + ' ' + v[1] + u[1] + +// ' ' + v[2] + u[2] + ' ' + v[3] + u[3] + ')'; +// +// }, + + webkitClipPath: function(value, unit) { + var v = value.webkitClipPath, + u = unit.webkitClipPath, + s = unit.webkitClipPathStyle, + i, l, style; + + if (s === 'circle') { + // circle(0% at 50% 50%) + return u[0] + '(' + v[0] + u[1] + ' at ' + v[1] + u[2] + ' ' + v[2] + u[3] + ')'; + } else if (s === 'polygon') { + // 'polygon(0 0, 0% 100%, 100% 0)' + style = s + '('; + for (i = 0, l = v.length; i < l; i += 2) { + style += (v[i] + u[i] + ' ' + v[i + 1] + u[i + 1]); + style += (i + 1 !== l - 1) ? ', ' : ')'; + } + return style; + } + }, + + _direct: function(type) { + return function(v) { + return v[type]; + } + }, + _rgbColor: function(type) { + return function(v) { + //console.log(' rgb(' + v[type][0] + ', ' + v[type][1] + ', ' + v[type][2] + ')'); + return 'rgb(' + v[type][0] + ', ' + v[type][1] + ', ' + v[type][2] + ')'; + } + } + }); + + /* + * Creates string based on CSS properties + */ + ns.CssStringCreator = base.singleTon(CssStringCreator); + +})(window, ns, ns.base); +(function(window, ns, base) { + 'use strict'; + + var CssParser = ns.CSSPropertyParser.getInstance(); + + var CssAnimationUtil = base.Class.extend({ + + _init: function() { + + // width unit + var self = this, color, + widthUnit, heightUnit, background, marginPadding, border, shadow; + + color = ['backgroundColor', 'color', + 'borderColor', 'borderTopColor', 'borderRightColor', 'borderLeftColor', 'borderBottomColor']; + + color.forEach(function(name) { + self[name] = function(animation) { + self.settingCssAnimation(name, animation, '_colorType'); + } + }); + + widthUnit = ['width', 'left', 'marginRight', 'marginLeft', 'paddingRight', 'paddingLeft', + 'marginTop', 'marginBottom', 'paddingBottom', 'paddingTop', + 'clipTop', 'clipBottom', 'clipRight', 'clipLeft', + 'borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderLeftWidth', 'borderBottomWidth', + 'clipTop', 'clipBottom', 'clipRight', 'clipLeft']; + widthUnit.forEach(function(name) { + self[name] = function(animation) { + self.settingCssAnimation(name, animation, '_unitType', 'width'); + } + }); + + heightUnit = ['height', 'top']; + heightUnit.forEach(function(name) { + self[name] = function(animation) { + self.settingCssAnimation(name, animation, '_unitType', 'height'); + } + }); + + background = ['backgroundPosition', 'backgroundSize']; + background.forEach(function(name) { + self[name] = function(animation) { + self.settingCssAnimation(name, animation, '_backgroundType'); + } + }); + + marginPadding = ['margin', 'padding']; + marginPadding.forEach(function(name) { + self[name] = function(animation) { + var from, to, i; + + if (animation.animationFromTo[name].length === 2) { + from = CssParser[name](animation.animationFromTo[name][0]); + to = CssParser[name](animation.animationFromTo[name][1]); + + for (i in to) { + animation.animationFromTo[i] = [from[i], to[i]]; + self[i](animation); + } + + } else { + to = CssParser[name](animation.animationFromTo[name]); + + for (i in to) { + animation.animationFromTo[i] = to[i]; + self[i](animation); + } + } + } + }); + + border = ['border', 'borderTop', 'borderRight', 'borderLeft', 'borderBottom']; + border.forEach(function(name) { + self[name] = function(animation) { + var from, to; + + if (animation.animationFromTo[name].length === 2) { + from = CssParser[name](animation.animationFromTo[name][0]); + to = CssParser[name](animation.animationFromTo[name][1]); + + animation.animationFromTo[name + 'Width'] = [from[name + 'Width'], to[name + 'Width']]; + animation.animationFromTo[name + 'Color'] = [from[name + 'Color'], to[name + 'Color']]; + } else { + to = CssParser[name](animation.animationFromTo[name]); + + animation.animationFromTo[name + 'Width'] = to[name + 'Width']; + animation.animationFromTo[name + 'Color'] = to[name + 'Color']; + } + + animation.unit[name + 'Style'] = to[name + 'Style']; + + self[name + 'Width'](animation); + self[name + 'Color'](animation); + } + }); + + border = ['border', 'borderTop', 'borderRight', 'borderLeft', 'borderBottom']; + border.forEach(function(name) { + self[name] = function(animation) { + var from, to; + + if (animation.animationFromTo[name].length === 2) { + from = CssParser[name](animation.animationFromTo[name][0]); + to = CssParser[name](animation.animationFromTo[name][1]); + + animation.animationFromTo[name + 'Width'] = [from[name + 'Width'], to[name + 'Width']]; + animation.animationFromTo[name + 'Color'] = [from[name + 'Color'], to[name + 'Color']]; + } else { + to = CssParser[name](animation.animationFromTo[name]); + + animation.animationFromTo[name + 'Width'] = to[name + 'Width']; + animation.animationFromTo[name + 'Color'] = to[name + 'Color']; + } + + animation.unit[name + 'Style'] = to[name + 'Style']; + + self[name + 'Width'](animation); + self[name + 'Color'](animation); + } + }); + + shadow = ['boxShadow', 'textShadow']; + shadow.forEach(function(name) { + self[name] = function(animation) { + self.settingCssAnimation(name, animation, '_shadowType'); + } + }); + + this.webkitClipPath = function(animation) { + this.settingCssAnimation('webkitClipPath', animation, '_webkitClipPathType'); + }; + + this.fontSize = function(animation) { + this.settingCssAnimation('fontSize', animation, '_fontSizeType'); + }; + + this.lineHeight = function(animation) { + this.settingCssAnimation('lineHeight', animation, '_unitType', 'lineHeight'); + }; + + this.opacity = function(animation) { + this.settingCssAnimation('opacity', animation); + }; + + this.WebkitTransform = function(name, animation) { + + var from, to, i, self = this; + + if (typeof animation.animationFromTo[name] === 'object' && animation.animationFromTo[name].length === 2) { + from = animation.animationFromTo[name][0]; + to = animation.animationFromTo[name][1]; + + } else { + from = animation.target.cur[name]; + to = animation.animationFromTo[name]; + } + + if (name === 'translateX' || name === 'translateY' || name === 'translateZ') { + (typeof from === 'string') && (from = this._getTranslateValue(name, animation, from)); + (typeof to === 'string') && (to = this._getTranslateValue(name, animation, to)); + } + + animation.fromTo[name] = [from, to]; + animation.target.from[name] = to; + animation.name.push(name); + }; + }, + + settingCssAnimation: function(name, animation, type, percentCriterion) { + var fromTo; + + // 1. animation parser + fromTo = animation.fromTo[name] = []; + + if (typeof animation.animationFromTo[name] === 'object' && + animation.animationFromTo[name].length === 2) { + fromTo[0] = animation.animationFromTo[name][0]; + fromTo[1] = animation.animationFromTo[name][1]; + } else { + fromTo[0] = window.getComputedStyle(animation.target.dom)[name]; + if (fromTo[0] === '' || fromTo[0] === 'auto' || fromTo[0] === 'none' || fromTo[0] === undefined) { + fromTo[0] = this._exceptGetStyle(animation.target.dom, name); + } + fromTo[1] = animation.animationFromTo[name]; + } + + fromTo[0] = CssParser[name](fromTo[0]); + fromTo[1] = CssParser[name](fromTo[1]); + + // type check + if (type) { + this[type] && this[type](name, animation, percentCriterion); + } + animation.name.push(name); + + //console.log(animation.fromTo[name]); + }, + + unitArray: function(name, animation, percentCriterion) { + var from = [], to = [], unit = [], i, len, f, t, cri, + fromTo = animation.fromTo[name]; + + for (i = 0, len = fromTo[0].length; i < len; i++) { + f = fromTo[0][i]; + t = fromTo[1][i]; + + if (f.unit !== t.unit) { + cri = (typeof percentCriterion === 'object' && percentCriterion[i] ? percentCriterion[i] : percentCriterion); + this._convertUnit(animation.target.dom, f, t, cri, name); + } + + from.push(f.number); + to.push(t.number); + unit.push(t.unit); + } + + animation.fromTo[name] = [from, to]; + animation.unit[name] = unit; + }, + +// TYPE Function + _colorType: function(name, animation) { + animation.target.cur[name] = new Uint8Array(3); + }, + + _fontSizeType: function(name, animation) { + var fromTo = animation.fromTo[name]; + + if (isNaN(fromTo[0].number)) { + this._getStringFontNumber(fromTo[0], animation.target.dom) + } + + if (isNaN(fromTo[1].number)) { + this._getStringFontNumber(fromTo[1], animation.target.dom) + } + + this._unitType(name, animation, 'fontSize'); + }, + + _backgroundType: function(name, animation) { + + if (animation.fromTo[name][0].length === 1) { + animation.fromTo[name][0].push({ + number: 50, + unit: '%' + }); + } + + if (animation.fromTo[name][1].length === 1) { + animation.fromTo[name][1].push({ + number: 50, + unit: '%' + }); + } + + this.unitArray(name, animation, ['width', 'height']); + }, + + _unitType: function(name, animation, criterion) { + var from = animation.fromTo[name][0], + to = animation.fromTo[name][1]; + + if (from.unit !== to.unit) { + this._convertUnit(animation.target.dom, from, to, criterion, name); + } + + animation.unit[name] = to.unit; + animation.target.unit[name] = to.unit; + animation.fromTo[name][0] = from.number; + animation.fromTo[name][1] = to.number; + + //animation.target.from[name] = to[0]; + + return false; + }, + + _webkitClipPathType: function(name, animation) { + var fromTo = animation.fromTo[name]; + + // todo: exception + animation.unit[name + 'Style'] = fromTo[1][0]; + fromTo[0].splice(0, 1); + fromTo[1].splice(0, 1); + + this.unitArray(name, animation, 'width'); + }, + + _shadowType: function(name, animation) { + var from = animation.fromTo[name][0], to = animation.fromTo[name][1], + animationFrom = [], animationTo = [], animationUnit = [], + shadowFrom, shadowTo, + unit, i, j, shadow, len, shadowLen; + + animation.unit[name] = animationUnit; + + for (i = 0, shadowLen = to.length; i < shadowLen; i++) { + + (!from[i]) && (from[i] = []); + shadowFrom = from[i]; + shadowTo = to[i]; + unit = []; + animationUnit.push(unit); + + for (j = 0, len = shadowTo.length - 1; j < len; j++) { + + unit.push(shadowTo[j].unit); + + if (shadowFrom[j] && shadowTo[j].unit !== (shadowFrom[j].unit)) { + this._convertUnit(animation.target.dom, shadowFrom[j], shadowTo[j], 'width', name); + } + + shadowTo[j] = shadowTo[j].number; + + shadowFrom[j] = (shadowFrom[j] ? shadowFrom[j].number : 0); + } + + shadowFrom[len] || (shadowFrom[len] = new Uint8Array(3)); + + } + + animation.cur[name] = base.deepCopy(to); + }, + + //TODO : not parser + _exceptGetStyle: function(dom, style) { + var result, imageUrl, img; + + if (style === 'left') { + result = dom.offsetLeft + 'px'; + } else if (style === 'top') { + result = dom.offsetTop + 'px'; + } else if (style === 'clip') { + result = 'rect(0px 0px 0px 0px)'; + } else if (style === 'boxShadow') { + result = '0px 0px 0px 0px black'; + } else if (style === 'textShadow') { + result = '0px 0px 0px black'; + } else if (style === 'backgroundPosition') { + result = '0px 0px'; + } else if (style === 'backgroundSize') { + imageUrl = this._getStyle(dom, 'backgroundImage'); + window.aa = img = new Image(); + img.src = imageUrl; + + if (img.width && img.height) { + result = img.width + 'px ' + img.height + 'px'; + } else { + result = '0px 0px'; + } + } + + if (result === undefined) { + result = '0px'; + } + + return result; + }, + + // get Style + _getCriterionEm: function(dom, criterion) { + return criterion === 'fontSize' ? 16 : (this._getStyle(dom, 'fontSize').number || 16); + }, + + _getCriterionPercent: function(dom, criterion, style) { + var parent = dom.parentNode, + parentValue, string, size, imgSize; + + if (style === 'lineHeight') { + return (this._getStyle(dom, 'fontSize').number || 16); + } else if (style === 'backgroundPosition') { + + size = this._getStyle(dom, criterion).number; + imgSize = this._getBackgroundImageSize(dom, criterion); + + return size - imgSize + 1; + } else if (style === 'backgroundSize') { + return this._getStyle(dom, criterion).number; + } + + parentValue = CssParser._getFloat(window.getComputedStyle(parent)[criterion]); + while (parentValue === '' && parent !== document.body) { + parent = parent.parentNode; + parentValue = CssParser._getFloat(window.getComputedStyle(parent)[criterion]); + } + + if (parentValue === 0 && (criterion === 'width' || criterion === 'height')) { + string = criterion.substring(0, 1).toUpperCase() + criterion.substring(1); + parentValue = window['inner' + string]; + } + + return parentValue; + }, + + _getStyle: function(dom, style) { + var s = window.getComputedStyle(dom)[style]; + s = CssParser[style](s); + return s; + }, + + _getBackgroundImageSize: function(dom, style) { + var imageUrl, img, + size = this._getStyle(dom, 'backgroundSize'); + + if (size[0].unit === 'auto') { + imageUrl = this._getStyle(dom, 'backgroundImage'); + img = new Image(); + img.src = imageUrl; + + if (style === undefined) { + return [img.width, img.height]; + } + return img[style]; + } else { + return size[(style === 'width' ? 0 : 1)].number; + } + + }, + + _getStringFontNumber: function(value, dom) { + var string = value.unit; + + if (string === 'normal' || string === 'initial') { + value.number = (this._getStyle(dom, 'fontSize').number || 16); + value.unit = 'px'; + } else if (string === 'xx-small') { + value.number = 0.5625; + value.unit = 'em'; + } else if (string === 'x-small') { + value.number = 0.625; + value.unit = 'em'; + } else if (string === 'small') { + value.number = 0.8125; + value.unit = 'em'; + } else if (string === 'medium') { + value.number = 1; + value.unit = 'em'; + } else if (string === 'large') { + value.number = 1.125; + value.unit = 'em'; + } else if (string === 'x-large') { + value.number = 1.5; + value.unit = 'em'; + } else if (string === 'xx-large') { + value.number = 2; + value.unit = 'em'; + } + }, + + _getTranslateValue: function(name, animation, value) { + var translate, result; + + translate = CssParser._unit(value); + if (translate.unit !== 'px') { + if (name === 'translateX' || name === 'translateZ') { + result = this._convertPx(animation.target.dom, translate.number, translate.unit, 'width'); + + } else if (name === 'translateY') { + result = this._convertPx(animation.target.dom, translate.number, translate.unit, 'height'); + } + } else { + result = translate.number; + } + + return result; + }, + + + // Unit Convert //TODO: refactoring + _convertUnit: function(dom, from, to, criterion, style) { + if (to.unit === 'em') { + from.number = this._convertEm(dom, from.number, from.unit, criterion, style); + } else if (to.unit === '%') { + from.number = this._convertPer(dom, from.number, from.unit, criterion, style); + } else if (to.unit === 'px') { + from.number = this._convertPx(dom, from.number, from.unit, criterion, style); + } else if (to.unit === 'cm') { + from.number = this._convertCm(dom, from.number, from.unit, criterion, style); + } else if (to.unit === 'pt') { + from.number = this._convertPt(dom, from.number, from.unit, criterion, style); + } + }, + + _convertEm: function(dom, value, unit, criterion, style) { + var fontSize = this._getCriterionEm(dom, criterion, style); + if (value === 0) { + return 0; + } + + if (unit === 'px') { + return value / fontSize; + } else if (unit === '%') { + return (value / 100 * this._getCriterionPercent(dom, criterion, style)) / fontSize; + } else if (unit === 'cm' || unit === 'pt') { + return this._convertPx(dom, value, unit, criterion, style) / fontSize; + } + + return false; + }, + + _convertPer: function(dom, value, unit, criterion, style) { + var parentValue = this._getCriterionPercent(dom, criterion, style); + + if (value === 0) { + return 0; + } + + if (unit === 'px') { + return value / parentValue * 100; + } else if (unit === 'em') { + return (value * this._getCriterionEm(dom, criterion, style)) / parentValue * 100; + } else if (unit === 'cm' || unit === 'pt') { + return this._convertPx(dom, value, unit, criterion, style) / parentValue * 100; + } + + return false; + }, + + _convertPx: function(dom, value, unit, criterion, style) { + if (value === 0) { + return 0; + } + + if (unit === '%') { + return value / 100 * this._getCriterionPercent(dom, criterion, style); + } else if (unit === 'em') { + return value * (value * this._getCriterionEm(dom, criterion, style)); + } else if (unit === 'cm') { + return value * 37.795; + } else if (unit === 'pt') { + return value * 1.3; + } + + return false; + }, + + _convertCm: function(dom, value, unit, criterion, style) { + var pxValue; + + if (value === 0) { + return 0; + } + + if (unit !== 'px') { + pxValue = this._convertPx(dom, value, unit, criterion, style); + } else { + pxValue = value; + } + + return pxValue * 0.02646; + }, + + _convertPt: function(dom, value, unit, criterion, style) { + var ptValue; + + if (value === 0) { + return 0; + } + + if (unit !== 'px') { + ptValue = this._convertPx(dom, value, unit, criterion, style); + } else { + ptValue = value; + } + + return ptValue * 0.75; + } + + }); + + /* + * Makes CSS properties for animation. If user uses CSS property, the animation is going to make it's properties. + */ + ns.CssAnimationUtil = ns.base.singleTon(CssAnimationUtil); + +})(window, ns, ns.base); +/* + * # Animation Util + * + * Makes utilities for animation such as stagger, option, pre-defined effect, and keyframe. + * This module provide additional feature to help SimpleAnimation. + * Animation Util convert pre-defined effect, keyframe, option. Simple Animation will use based on this information. + * Also, Animation Util check whether stagger is on or not. + * + * @class ns.AnimationUtil + */ +(function(window, ns, base) { + var AnimationUtil = { + + /** + * Returns option for animation. Because option value can be various type, this function make unified expression. + * @method optionAnalyzer + * @param {Object|Number} arg1 + * The arg1 can be option Object as {duration: 1000, ease: 'bounceOut', delay: 100} OR number value that indicate duration + * @param {Object|undefined} arg2 + * The arg2 can be Object as {ease: 'bounceOut', delay: 100} OR undefined + * @return {Object} + * @member ns.AnimationUtil + * @static + */ + optionAnalyzer: function(arg1, arg2) { + var option; + + if (arg1 !== undefined) { + if (typeof arg1 === 'number') { + if (arg2 && typeof arg2 === 'object') { + option = arg2; + } else { + option = {}; + } + option.duration = arg1; + } else if (typeof arg1 === 'object') { + option = arg1; + } + } else { + option = {}; + option.duration = 1000; + } + return option; + }, + + /** + * Checks stagger option that included option of animation. If stagger is set, delay values of all targets are set in serial order automatically. + * @method checkStagger + * @param {Object} targets + * If stagger option is exists, this targets will be applied delay in serial order. + * @param {Object} option + * the option include stagger, drag, ease, and so on. + * @param {Function} callback + * The callback function will be called after this function. Actually, callback handle option value about targets. + * @member ns.AnimationUtil + * @static + */ + checkStagger: function(targets, option, callback) { + var i, len, o; + this.animations = []; + + // stagger + for (i = 0, len = targets.length; i < len; i++) { + o = ns.base.deepCopy(option); + + if (option.stagger) { + o.delay = option.stagger * i + (option.delay || 0); + o.reverseDelay = option.stagger * (len - i); + } + + if (i !== 0 && option.drag) { + o.duration += (option.drag * i); + } + + if (i === 0 && option.onStart) { + o.onStart = option.onStart; + } + /* else if (i === len - 1 && option.onComplete) { + o.onComplete = option.onComplete; + }*/ + + callback(targets[i], o, i); + } + }, + + /** + * Creates Keyframe for animation. If user make keyframe, this function will be called and make appropriate value for animation. + * @method createKeyFrame + * @param {Object} frame + * The frame has keyframe information. Keyframe animation based on frame. + * @param {Object} option + * The Option has ease, delay, duration, and so on. + * @param {Function} callback + * After handling based on frame and option, callback will invoked with result of handling. + * @member ns.AnimationUtil + * @static + */ + createKeyFrame: function(frame, option, callback) { + var i, j, l, preDuration, ft, o, offset = [], frames = []; + + for (i in frame) { + offset.push(parseFloat(i)); + } + + offset.sort(function(a, b) { + return a - b; + }); + preDuration = offset[0]; + + for (i = 0, l = offset.length - 1; i < l; i++) { + o = ns.base.deepCopy(option); + ft = {}; + + for (j in frame[offset[i + 1]]) { + if (frame[offset[i]][j] !== undefined) { + ft[j] = [frame[offset[i]][j], frame[offset[i + 1]][j]] + } else { + ft[j] = frame[offset[i + 1]][j]; + } + } + + o.duration = option.duration * (offset[i + 1] - preDuration); + preDuration = offset[i + 1]; + + if (i === 0) { + + option.onStart && (o.onStart = option.onStart); + option.delay && (o.delay = option.delay); + o.reverseDelay = 0; + + } else { + + option.delay && (o.delay = 0); + option.stagger && (o.delay = 0); + + if (i === l - 1) { + + option.onComplete && (o.onComplete = option.onComplete); + + + } else { + o.reverseDelay = 0; + } + } + +// if(option.stagger) { +// if(i !== 0) { +// o.delay = 0; +// } +// if(i !== l-1) { +// o.reverseDelay = 0; +// } +// } +// console.log(o.delay); + callback(ft, o, i); + } + }, + + /** + * Analyzes effect as pre-defined. This function make keyframe based frame, cubic-bezier based ease, transformOrigin value, visibility. + * @method effectAnalyzer + * @param {Object} target + * @param {String} animation + * The animation is a effect as a String. + * @return {Array} + * @member ns.AnimationUtil + * @static + */ + effectAnalyzer: function(target, animation) { + var predefined, frame, ease, transformOrigin, visibility, + width = ns.CssAnimationUtil.getInstance()._getCriterionPercent(target.dom, 'width'), + height = ns.CssAnimationUtil.getInstance()._getCriterionPercent(target.dom, 'height'); + predefined = animation; + + target.dom.style.opacity = target.dom.style.opacity ? target.dom.style.opacity : 1; + + if (predefined === 'pulse') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY}, + 0.5: {scaleX: 1.05 * target.cur.scaleX, scaleY: 1.05 * target.cur.scaleY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY} + }; + } else if (predefined === 'rollIn') { + frame = { + 0: {translateX: -100 + target.cur.translateX, rotateZ: -120 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {translateX: 0 + target.cur.translateX, rotateZ: 0 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + + } else if (predefined === 'rollOut') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {translateX: 200 + target.cur.translateX, rotateZ: 120 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'bounce') { + frame = { + 0: {translateY: 0 + target.cur.translateY}, + 0.2: {translateY: 0 + target.cur.translateY}, + 0.4: {translateY: -30 + target.cur.translateY}, + 0.5: {translateY: 0 + target.cur.translateY}, + 0.7: {translateY: -15 + target.cur.translateY}, + 0.8: {translateY: 0 + target.cur.translateY}, + 0.9: {translateY: -4 + target.cur.translateY}, + 1: {translateY: 0 + target.cur.translateY} + }; + ease = ['bounce1', 'bounce1', 'bounce2', 'bounce1', 'bounce2', 'bounce1', '', 'bounce1']; + transformOrigin = 'center bottom'; + } else if (predefined === 'bounceIn') { + frame = { + 0: {scaleX: 0.3 * target.cur.scaleX, scaleY: 0.3 * target.cur.scaleY}, + 0.2: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY}, + 0.4: {scaleX: 0.9 * target.cur.scaleX, scaleY: 0.9 * target.cur.scaleY}, + 0.6: {scaleX: 1.03 * target.cur.scaleX, scaleY: 1.03 * target.cur.scaleY}, + 0.8: {scaleX: 0.97 * target.cur.scaleX, scaleY: 0.97 * target.cur.scaleY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY} + }; + ease = ['bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1']; + } else if (predefined === 'bounceInDown') { + frame = { + 0: {translateY: -3000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity}, + 0.6: {translateY: 25 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.75: {translateY: -10 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.9: {translateY: 5 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity} + }; + ease = ['bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1']; + } else if (predefined === 'bounceInLeft') { + frame = { + 0: {translateX: -3000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity}, + 0.6: {translateX: 25 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.75: {translateX: -10 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.9: {translateX: 5 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity} + }; + ease = ['bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1']; + } else if (predefined === 'bounceInRight') { + frame = { + 0: {translateX: 3000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity}, + 0.6: {translateX: -25 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.75: {translateX: 10 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.9: {translateX: -5 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity} + }; + ease = ['bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1']; + } else if (predefined === 'bounceInUp') { + frame = { + 0: {translateY: 3000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity}, + 0.6: {translateY: -25 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.75: {translateY: 10 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.9: {translateY: -5 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity} + }; + ease = ['bounce1', 'bounce1', 'bounce1', 'bounce1', 'bounce1']; + } else if (predefined === 'bounceOut') { + frame = { + 0.2: {opacity: 0 * target.dom.style.opacity, scaleX: 0.9 * target.cur.scaleX, scaleY: 0.9 * target.cur.scaleY}, + 0.5: {opacity: 1 * target.dom.style.opacity, scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY}, + 1: {opacity: 0 * target.dom.style.opacity, scaleX: 0.3 * target.cur.scaleX, scaleY: 0.3 * target.cur.scaleY} + }; + } else if (predefined === 'bounceOutDown') { + frame = { + 0: {translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.1: {translateY: 10 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.45: {translateY: -20 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {translateY: 2000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'bounceOutLeft') { + frame = { + 0: {translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.2: {translateX: 20 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {translateX: -2000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'bounceOutRight') { + frame = { + 0: {translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.2: {translateX: -20 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {translateX: 2000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'bounceOutUp') { + frame = { + 0: {translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.2: {translateY: -10 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.45: {translateY: 20 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {translateY: -2000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'zoomIn') { + frame = { + 0: {scaleX: 0.3 * target.cur.scaleX, scaleY: 0.3 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity}, + 0.5: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity} + }; + } else if (predefined === 'zoomInDown') { + frame = { + 0: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity, translateX: 0 + target.cur.translateX, translateY: -1000 + target.cur.translateY}, + 0.6: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX, translateY: 60 + target.cur.translateY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX, translateY: 0 + target.cur.translateY} + }; + ease = ['zoomInDown', 'backOut']; + } else if (predefined === 'zoomInLeft') { + frame = { + 0: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity, translateX: -1000 + target.cur.translateX}, + 0.6: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateX: 10 + target.cur.translateX}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateX} + }; + ease = ['zoomInDown', 'backOut']; + } else if (predefined === 'zoomInRight') { + frame = { + 0: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity, translateX: 1000 + target.cur.translateX, translateY: target.cur.translateY}, + 0.6: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateX: -10 + target.cur.translateX, translateY: target.cur.translateY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateY: target.cur.translateY} + }; + ease = ['zoomInDown', 'backOut']; + } else if (predefined === 'zoomInUp') { + frame = { + 0: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity, translateY: 1000 + target.cur.translateY}, + 0.6: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateY: -60 + target.cur.translateY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY} + }; + ease = ['zoomInDown', 'backOut']; + } else if (predefined === 'zoomOut') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 0.6: {scaleX: 0.3 * target.cur.scaleX, scaleY: 0.3 * target.cur.scaleY, opacity: 0 * target.dom.style.opacity}, + 1: {opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'zoomOutDown') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.4: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, translateY: -60 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, translateY: 2000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity} + }; + ease = ['zoomInDown', 'backOut']; + transformOrigin = 'center bottom'; + } else if (predefined === 'zoomOutLeft') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.4: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, translateX: 42 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, translateX: -2000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'left center'; + } else if (predefined === 'zoomOutRight') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, translateX: 0 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 0.4: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, translateX: -42 + target.cur.translateX, opacity: 1 * target.dom.style.opacity}, + 1: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, translateX: 2000 + target.cur.translateX, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'right center'; + } else if (predefined === 'zoomOutUp') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 0.4: {scaleX: 0.475 * target.cur.scaleX, scaleY: 0.475 * target.cur.scaleY, translateY: 60 + target.cur.translateY, opacity: 1 * target.dom.style.opacity}, + 1: {scaleX: 0.1 * target.cur.scaleX, scaleY: 0.1 * target.cur.scaleY, translateY: -2000 + target.cur.translateY, opacity: 0 * target.dom.style.opacity} + }; + ease = ['zoomInDown', 'backOut']; + transformOrigin = 'center bottom'; + } else if (predefined === 'slideInDown') { + frame = { + 0: {translateY: (height * -1) + target.cur.translateY}, + 1: {translateY: 0 + target.cur.translateY} + }; + visibility = 'visible'; + } else if (predefined === 'slideInLeft') { + frame = { + 0: {translateX: (width * -1) + target.cur.translateX}, + 1: {translateX: 0 + target.cur.translateX} + }; + visibility = 'visible'; + } else if (predefined === 'slideInRight') { + frame = { + 0: {translateX: (width * 1) + target.cur.translateX}, + 1: {translateX: 0 + target.cur.translateX} + }; + visibility = 'visible'; + } else if (predefined === 'slideInUp') { + frame = { + 0: {translateY: (height * 1) + target.cur.translateY}, + 1: {translateY: 0 + target.cur.translateY} + }; + visibility = 'visible'; + } else if (predefined === 'slideOutDown') { + frame = { + 0: {translateY: 0 + target.cur.translateY}, + 1: {translateY: (height * 1) + target.cur.translateY} + }; + visibility = 'hidden'; + } else if (predefined === 'slideOutLeft') { + frame = { + 0: {translateX: 0 + target.cur.translateX}, + 1: {translateX: (width * -1) + target.cur.translateX} + }; + visibility = 'hidden'; + } else if (predefined === 'slideOutRight') { + frame = { + 0: {translateX: 0 + target.cur.translateX}, + 1: {translateX: (width * 1) + target.cur.translateX} + }; + visibility = 'hidden'; + } else if (predefined === 'slideOutUp') { + frame = { + 0: {translateY: 0 + target.cur.translateY}, + 1: {translateY: (height * -1) + target.cur.translateY} + }; + visibility = 'hidden'; + } else if (predefined === 'flash') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 0.25: {opacity: 0 * target.dom.style.opacity}, + 0.5: {opacity: 1 * target.dom.style.opacity}, + 0.75: {opacity: 0 * target.dom.style.opacity}, + 1: {opacity: 1 * target.dom.style.opacity} + }; + } else if (predefined === 'rubberBand') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY}, + 0.3: {scaleX: 1.25 * target.cur.scaleX, scaleY: 0.75 * target.cur.scaleY}, + 0.4: {scaleX: 0.75 * target.cur.scaleX, scaleY: 1.25 * target.cur.scaleY}, + 0.5: {scaleX: 1.15 * target.cur.scaleX, scaleY: 0.85 * target.cur.scaleY}, + 0.65: {scaleX: 0.95 * target.cur.scaleX, scaleY: 1.05 * target.cur.scaleY}, + 0.75: {scaleX: 1.05 * target.cur.scaleX, scaleY: 0.95 * target.cur.scaleY}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY} + }; + } else if (predefined === 'shake') { + frame = { + 0: {translateX: 0 + target.cur.translateX}, + 0.1: {translateX: -10 + target.cur.translateX}, + 0.2: {translateX: 10 + target.cur.translateX}, + 0.3: {translateX: -10 + target.cur.translateX}, + 0.4: {translateX: 10 + target.cur.translateX}, + 0.5: {translateX: -10 + target.cur.translateX}, + 0.6: {translateX: 10 + target.cur.translateX}, + 0.7: {translateX: -10 + target.cur.translateX}, + 0.8: {translateX: 10 + target.cur.translateX}, + 0.9: {translateX: -10 + target.cur.translateX}, + 1: {translateX: 0 + target.cur.translateX} + }; + } else if (predefined === 'swing') { + frame = { + 0: {rotateZ: 0 + target.cur.rotateZ}, + 0.2: {rotateZ: 15 + target.cur.rotateZ}, + 0.4: {rotateZ: -10 + target.cur.rotateZ}, + 0.6: {rotateZ: 5 + target.cur.rotateZ}, + 0.8: {rotateZ: -5 + target.cur.rotateZ}, + 1: {rotateZ: 0 + target.cur.rotateZ} + }; + transformOrigin = 'top center'; + } else if (predefined === 'tada') { + frame = { + 0: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, rotateZ: 0 + target.cur.rotateZ}, + 0.15: {scaleX: 0.9 * target.cur.scaleX, scaleY: 0.9 * target.cur.scaleY, rotateZ: -3 + target.cur.rotateZ}, + 0.3: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: 3 + target.cur.rotateZ}, + 0.4: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: -3 + target.cur.rotateZ}, + 0.5: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: 3 + target.cur.rotateZ}, + 0.6: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: -3 + target.cur.rotateZ}, + 0.7: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: 3 + target.cur.rotateZ}, + 0.8: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: -3 + target.cur.rotateZ}, + 0.9: {scaleX: 1.1 * target.cur.scaleX, scaleY: 1.1 * target.cur.scaleY, rotateZ: 3 + target.cur.rotateZ}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, rotateZ: 0 + target.cur.rotateZ} + }; + } else if (predefined === 'wobble') { + frame = { + 0: {translateX: 0 + target.cur.translateX, rotateZ: 0 + target.cur.rotateZ}, + 0.15: {translateX: (width * -0.25) + target.cur.translateX, rotateZ: -5 + target.cur.rotateZ}, + 0.3: {translateX: (width * 0.2) + target.cur.translateX, rotateZ: 3 + target.cur.rotateZ}, + 0.45: {translateX: (width * -0.15) + target.cur.translateX, rotateZ: -3 + target.cur.rotateZ}, + 0.6: {translateX: (width * 0.1) + target.cur.translateX, rotateZ: 2 + target.cur.rotateZ}, + 0.75: {translateX: (width * -0.05) + target.cur.translateX, rotateZ: -1 + target.cur.rotateZ}, + 1: {translateX: 0 + target.cur.translateX, rotateZ: 0 + target.cur.rotateZ} + }; + } else if (predefined === 'jello') { + frame = { + 0: {skewX: 0 + target.cur.skewX, skewY: 0 + target.cur.skewY}, + 0.22: {skewX: -12.5 + target.cur.skewX, skewY: -12.5 + target.cur.skewY}, + 0.33: {skewX: 6.25 + target.cur.skewX, skewY: 6.25 + target.cur.skewY}, + 0.44: {skewX: -3.125 + target.cur.skewX, skewY: -3.125 + target.cur.skewY}, + 0.55: {skewX: 1.5625 + target.cur.skewX, skewY: 1.5625 + target.cur.skewY}, + 0.66: {skewX: -0.78125 + target.cur.skewX, skewY: -0.78125 + target.cur.skewY}, + 0.77: {skewX: 0.390625 + target.cur.skewX, skewY: 0.390625 + target.cur.skewY}, + 0.88: {skewX: -0.1953125 + target.cur.skewX, skewY: -0.1953125 + target.cur.skewY}, + 1: {skewX: 0 + target.cur.skewX, skewY: 0 + target.cur.skewY} + }; + transformOrigin = 'center'; + } else if (predefined === 'fadeIn') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity}, + 1: {opacity: 1 * target.dom.style.opacity} + }; + } else if (predefined === 'fadeInDown') { + frame = { + 0: {translateY: (height * -1) + target.cur.translateY, opacity: 0 * target.dom.style.opacity}, + 1: {translateY: 0 + target.cur.translateY, opacity: 1 * target.dom.style.opacity} + }; + } else if (predefined === 'fadeInDownBig') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateY: -2000 + target.cur.translateY}, + 1: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY} + }; + } else if (predefined === 'fadeInLeft') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateX: (width * -1) + target.cur.translateX}, + 1: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX} + }; + } else if (predefined === 'fadeInLeftBig') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateX: -2000 + target.cur.translateX}, + 1: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX} + }; + } else if (predefined === 'fadeInRight') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateX: (width * 1) + target.cur.translateX}, + 1: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX} + }; + } else if (predefined === 'fadeInRightBig') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateX: 2000 + target.cur.translateX}, + 1: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX} + }; + } else if (predefined === 'fadeInUp') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateY: (height * 1) + target.cur.translateY}, + 1: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY} + }; + + } else if (predefined === 'fadeInUpBig') { + frame = { + 0: {opacity: 0 * target.dom.style.opacity, translateY: 2000 + target.cur.translateY}, + 1: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY} + }; + } else if (predefined === 'fadeOut') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'fadeOutDown') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY}, + 1: {opacity: 0 * target.dom.style.opacity, translateY: (height * 1) + target.cur.translateY} + }; + } else if (predefined === 'fadeOutDownBig') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY}, + 1: {opacity: 0 * target.dom.style.opacity, translateY: 2000 + target.cur.translateY} + }; + } else if (predefined === 'fadeOutLeft') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX}, + 1: {opacity: 0 * target.dom.style.opacity, translateX: (width * -1) + target.cur.translateX} + }; + } else if (predefined === 'fadeOutLeftBig') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX}, + 1: {opacity: 0 * target.dom.style.opacity, translateX: -2000 + target.cur.translateX} + }; + } else if (predefined === 'fadeOutRight') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX}, + 1: {opacity: 0 * target.dom.style.opacity, translateX: (width * 1) + target.cur.translateX} + }; + } else if (predefined === 'fadeOutRightBig') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateX: 0 + target.cur.translateX}, + 1: {opacity: 0 * target.dom.style.opacity, translateX: 2000 + target.cur.translateX} + }; + } else if (predefined === 'fadeOutUp') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY}, + 1: {opacity: 0 * target.dom.style.opacity, translateY: (height * -1) + target.cur.translateY} + }; + } else if (predefined === 'fadeOutUpBig') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity, translateY: 0 + target.cur.translateY}, + 1: {opacity: 0 * target.dom.style.opacity, translateY: -2000 + target.cur.translateY} + }; + } else if (predefined === 'flip') { + frame = { + 0: {rotateY: -360 + target.cur.rotateY, perspective: 400}, + 0.4: {rotateY: -190 + target.cur.rotateY, translateZ: 150 + target.cur.translateZ, perspective: 400}, + 0.5: {rotateY: -170 + target.cur.rotateY, translateZ: 150 + target.cur.translateZ, perspective: 400}, + 0.8: {scaleX: 0.95 * target.cur.scaleX, scaleY: 0.95 * target.cur.scaleY, perspective: 400}, + 1: {scaleX: 1 * target.cur.scaleX, scaleY: 1 * target.cur.scaleY, rotateY: 0 + target.cur.rotateY, translateZ: 0 + target.cur.translateZ, perspective: 400} + }; + ease = ['easeIn', 'easeIn', 'easeIn', 'easeIn', 'easeIn']; + } else if (predefined === 'flipInX') { + frame = { + 0: {rotateX: 90 + target.cur.rotateX, perspective: 400, opacity: 0 * target.dom.style.opacity}, + 0.4: {rotateX: -20 + target.cur.rotateX, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 0.6: {rotateX: 10 + target.cur.rotateX, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 0.8: {rotateX: -5 + target.cur.rotateX, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 1: {rotateX: 0 + target.cur.rotateX, perspective: 400, opacity: 1 * target.dom.style.opacity} + }; + ease = ['easeIn', 'easeIn', 'easeIn', 'easeIn', 'easeIn']; + } else if (predefined === 'flipInY') { + frame = { + 0: {rotateY: 90 + target.cur.rotateY, perspective: 400, opacity: 0 * target.dom.style.opacity}, + 0.4: {rotateY: -20 + target.cur.rotateY, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 0.6: {rotateY: 10 + target.cur.rotateY, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 0.8: {rotateY: -5 + target.cur.rotateY, perspective: 400, opacity: 1 * target.dom.style.opacity}, + 1: {rotateY: 0 + target.cur.rotateY, perspective: 400, opacity: 1 * target.dom.style.opacity} + }; + ease = ['easeIn', 'easeIn', 'easeIn', 'easeIn', 'easeIn']; + } else if (predefined === 'flipOutX') { + frame = { + 0: {perspective: 400}, + 0.3: {perspective: 400, rotateX: -20 + target.cur.rotateX, opacity: 1 * target.dom.style.opacity}, + 1: {perspective: 400, rotateX: 90 + target.cur.rotateX, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'flipOutY') { + frame = { + 0: {perspective: 400}, + 0.3: {perspective: 400, rotateY: -15 + target.cur.rotateY, opacity: 1 * target.dom.style.opacity}, + 1: {perspective: 400, rotateY: 90 + target.cur.rotateY, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'lightSpeedIn') { + frame = { + 0: {translateX: (width * 1) + target.cur.translateX, skewX: -30 + target.cur.skewX, opacity: 0 * target.dom.style.opacity}, + 0.6: {translateX: 0 + target.cur.translateX, skewX: 20 + target.cur.skewX, opacity: 1 * target.dom.style.opacity}, + 0.8: {translateX: 0 + target.cur.translateX, skewX: -5 + target.cur.skewX, opacity: 1 * target.dom.style.opacity}, + 1: {translateX: 0 + target.cur.translateX, skewX: 0 + target.cur.skewX, opacity: 1 * target.dom.style.opacity} + }; + } else if (predefined === 'lightSpeedOut') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {translateX: (width * 1) + target.cur.translateX, skewX: 30 + target.cur.skewX, opacity: 0 * target.dom.style.opacity} + }; + } else if (predefined === 'rotateIn') { + frame = { + 0: {rotateZ: -200 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {rotateZ: 0 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + transformOrigin = 'center'; + } else if (predefined === 'rotateInDownLeft') { + frame = { + 0: {rotateZ: -45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {rotateZ: 0 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + + transformOrigin = 'left bottom'; + } else if (predefined === 'rotateInDownRight') { + frame = { + 0: {rotateZ: 45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {rotateZ: 0 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + transformOrigin = 'right bottom'; + } else if (predefined === 'rotateInUpLeft') { + frame = { + 0: {rotateZ: 45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {rotateZ: +target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + transformOrigin = 'left bottom'; + } else if (predefined === 'rotateInUpRight') { + frame = { + 0: {rotateZ: -90 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity}, + 1: {rotateZ: 0 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity} + }; + transformOrigin = 'right bottom'; + } else if (predefined === 'rotateOut') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {rotateZ: 200 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'center'; + } else if (predefined === 'rotateOutDownLeft') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {rotateZ: 45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'left bottom'; + } else if (predefined === 'rotateOutDownRight') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {rotateZ: -45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'right bottom'; + } else if (predefined === 'rotateOutUpLeft') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {rotateZ: -45 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'left bottom'; + } else if (predefined === 'rotateOutUpRight') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 1: {rotateZ: 90 + target.cur.rotateZ, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'right bottom'; + } else if (predefined === 'hinge') { + frame = { + 0: {opacity: 1 * target.dom.style.opacity}, + 0.2: {rotateZ: 80 + target.cur.rotateZ}, + 0.4: {rotateZ: 60 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity}, + 0.6: {rotateZ: 80 + target.cur.rotateZ}, + 0.8: {rotateZ: 60 + target.cur.rotateZ, opacity: 1 * target.dom.style.opacity}, + 1: {translateY: 700 + target.cur.translateY, opacity: 0 * target.dom.style.opacity} + }; + transformOrigin = 'top left'; + ease = ['easeInOut', 'easeInOut', 'easeInOut', 'easeInOut', 'easeInOut', 'easeInOut']; + } else { + throw new Error('the name of animation is not exists'); + } + + return [frame, ease, transformOrigin, visibility]; + } + }; + + ns.AnimationUtil = AnimationUtil; +})(window, ns, ns.base); +// TODO + +(function(window, ns, base) { + var _singleton; + + var ObjectManager = base.Class.extend({ + + _init: function() { + if (_singleton !== undefined) { + _singleton = new this(); + return _singleton; + } + this.targetObjects = []; + + return this; + }, + + /** + * Add animation object to manager. + * @method addTarget + * @param {target} animation object + * @member ns.ObjectManager.addTarget + * @private + */ + addTarget: function(target) { + this.targetObjects.push(target); + target.map = new ns.base.WeakMap(); + }, + + /** + * Create animation object. + * @method getObject + * @param {target} animation object + * @member ns.ObjectManager.getObject + * @private + */ + getObject: function(obj) { + + if (obj instanceof ns.AnimationObject) { + return obj; + } + + for (var i = 0, len = this.targetObjects.length; i < len; i++) { + if(obj instanceof this.targetObjects[i].$type) { + + var object = this.targetObjects[i].map.get(obj); + + if(object === undefined) { + object = new ns[this.targetObjects[i].$namespace](obj); + this.targetObjects[i].map.set(obj, object); + } + return object; + } + } + + throw 'CannotCreateObject'; + + return; + }, + + + static: { + /** + * Return ObjectManger object + * @method getInstance + * @return {object} + * @member ns.ObjectManager.getInstance + * @static + */ + getInstance: function() { + if (_singleton === undefined) { + _singleton = new ObjectManager(); + } + return _singleton; + }, + + /** + * Create Animation Object by using plugin + * @method plugin + * @param {object} + * @member ns.ObjectManager.plugin + * @static + */ + plugin: function(definition) { + var keywordTest = /^\$(?:namespace|constructor|type)$/; + + if( (!definition.$constructor) ) { + return; + } + // TODO : $namespace, type 예외 처리 + function Class() { + ns.AnimationObject.call(this); + definition.$constructor.apply(this, arguments); + } + + Class.prototype = new ns.AnimationObject(); + Class.prototype.constructor = Class; + + for(var name in definition) { + if(keywordTest.test(name)) { + continue; + } + + Class.prototype[name] = typeof definition[name] === 'function' && definition[name]; + } + + ns[definition.$namespace] = Class; + + this.getInstance().addTarget(definition); + + return Class; + } + } + }); + + /* + * Manages objects that will be animated. + */ + ns.ObjectManager = ObjectManager; + +})(window, ns, ns.base); + + + +(function(window) { + 'use strict'; + + (function(window, ns, base) { + var AnimationObject = ns.base.Class.extend({ + _init: function() { + this.from = new ns.Transform(); + this.cur = base.copy(this.from); + + this.updateSeek = false; + this.updateSeekProperty = []; + }, + + getFrom: function(to) { + var v = {}; + var to = to.animation; + for(var i in to){ + v[i] = this.from[i]; + this.from[i] = to[i]; + } + return v; + }, + + setFrom: function(v) { + this.from.set(v); + }, + translate: function() { + + }, + rotate: function() { + + } + }); + + /* + * Manages animationObject. + */ + ns.AnimationObject = AnimationObject; + + })(window, ns, ns.base); + +})(window); +(function(window, ns, base) { + 'use strict'; + var CssAnimationUtil = ns.CssAnimationUtil.getInstance(), + CssStringCreator = ns.CssStringCreator.getInstance(); + + /* + * Constructs and Sets based on DOMObject. DOM Object is the one of target for animation. + */ + + ns.ObjectManager.plugin({ + $namespace: 'DomObject', + $type: window.HTMLElement, + $constructor: function(dom) { + this.dom = dom; + //this.style = dom.style; + this.unit = {}; + this._perspective = false; + }, + + /** + * Render dom object on screen. + * @method render + * @param {value} update target value + * @param {unit} unix + * @member ns.DomObject + * @private + */ + render: function(tweenInfo) { + var i, u = tweenInfo.updateProperty, l; + for (i = 0; l = u[i]; i++) { + tweenInfo.targetStyle[l] = CssStringCreator[l](this, tweenInfo.unit); + } + //var isUpdateTransform = false; + // + //for(var i in updateValue) { + // if(!this.isTransform(i) && this.dom.style[i] !== undefined) { + // this.dom.style[i] = CssStringCreator[i](updateValue, unit); + // } else { + // if(!isUpdateTransform) { + // this.dom.style.WebkitTransform = CssStringCreator.WebkitTransform(updateValue); + // isUpdateTransform = true; + // } + // } + //} + }, + + objectRender: function(updateValue) { + var isUpdateTransform = false; + + for (var i in updateValue) { + if (!this.isTransform(i) && this.dom.style[i] !== undefined) { + this.dom.style[i] = CssStringCreator[i](updateValue, unit); + } else { + if (!isUpdateTransform) { + this.dom.style.WebkitTransform = CssStringCreator.WebkitTransform(updateValue); + isUpdateTransform = true; + } + } + } + }, + + /** + * Create tween object in order to animate dom object. + * @method createTweenObject + * @param {value} animation from value + * @param {value} animation to value + * @param {value} animation option including duration, delay, ease ans so on. + * @member ns.DomObject + * @private + */ + createTweenInfo: function(fromTo, option, needFromTo) { + var info = { + fromTo: {}, + animationFromTo: fromTo, + cur: this.cur, + option: option, + name: [], + unit: {}, + target: this, + targetStyle: this.dom.style, + updateProperty: [] + }; + + if (needFromTo) { + this.setAnimationFromTo(info); + } + + return info; + }, + + setAnimationFromTo: function(obj) { + var isTransform = false, + fromTo = obj.animationFromTo, + i; + + for (i in fromTo) { + if (this.isTransform(i)) { + CssAnimationUtil.WebkitTransform(i, obj); + if (!isTransform) { + obj.updateProperty.push('WebkitTransform'); + isTransform = true; + } + } else if (i === 'perspective') { + this._perspective = base.isNumber(fromTo[i]) ? fromTo[i] : (base.isNumber(fromTo[i][1]) ? fromTo[i][1] : 0); + this.cur.perspective = this._perspective; + } else { + if (CssAnimationUtil[i]) { + CssAnimationUtil[i](obj); + obj.updateProperty.push(i); + } + } + + } + }, + /** + * Check if it is transform or not. + * @method isTransform + * @param {string} + * @return {boolean} + * @member ns.DomObject + * @private + */ + isTransform: function(i) { + if (i === undefined || i === null) { + return; + } + if (i === 'translateX' || i === 'translateY' || i === 'translateZ' || + i === 'rotateX' || i === 'rotateY' || i === 'rotateZ' || + i === 'scaleX' || i === 'scaleY' || i === 'skewX' || i === 'skewY' /*|| i === 'perspective'*/) { + return true; + + } + return false; + }, + + /** + * Set perspective of dom object. + * @method perspective + * @param {number} perspective value + * @member ns.DomObject + * @private + */ + perspective: function(n) { + if (n === undefined || n === null) { + return; + } + if (!ns.base.isNumber(n)) { + return; + } + this._perspective = n; + this.cur.perspective = n; + }, + + /** + * Set animation value of dom object + * @method set + * @param {value} animation value + * @member ns.DomObject + * @private + */ + set: function(v) { + if (v === undefined || v === null) { + return; + } + for (var i in v) { + if (this.isTransform(i)) { + this.from[i] = v[i]; + this.cur[i] = v[i]; + } else if (i === 'perspective') { + this.perspective(v[i]); + } else { + this.dom.style[i] = v[i]; + } + } + this.objectRender(base.deepCopy(this.from)); + } + }); +})(window, ns, ns.base); + +/** + * # TAU Animation + * + * Provides features that make and control animation. + * Simple Animation has relevance to Tween Animator. + * As you can see below APIs, almost APIs make Tween-able object and control animation. + * + * @example + * #### using tween and tween from ~ to + * + * $('#box').tween({left: 200}, {duration: 1000, ease: 'bounceInOut', onComplete: function() { + * console.log('animation complete'); + * } + * }); + * $('#box').tween({left: [200, 300]} {duration: 1000, ease: 'bounceInOut', onComplete: function() { + * console.log('animation complete'); + * } + * }); + * + * + * #### using tween and tween from ~ to as chaining + * + * var box = document.createElement('div'); + * box.tween({rotateZ: 120}, 1000) + * .tween({left: 200}, 1000) + * .tween({left: [200, 400], top: 100}, 1000); + * + * #### effect animation with stagger + * + * $('.box').animate('bounce', {duration: 1000, stagger: 200}); + * + * + * @class tau.animation.SimpleAnimationMixinObject + */ +(function(window, ns, base) { + 'use strict'; + + var ObjectManager = ns.ObjectManager.getInstance(); + + var SimpleAnimationMixinObject = { + /** + * Adds tween animation with animation information and target is animated. + * @method tween + * @member tau.animation.SimpleAnimationMixinObject + * @public + */ + tween: function(fromTo, arg1, arg2) { + var option; + + if (!this.simpleAnimation) { + if (this.length) { + this.simpleAnimation = new ns.SimpleAnimationGroup(this); + } else { + this.simpleAnimation = new ns.SimpleAnimation(this); + } + } + + option = ns.AnimationUtil.optionAnalyzer(arg1, arg2); + this.simpleAnimation.add(fromTo, option); + this.simpleAnimation.play(); + + return this; + }, + + /** + * Stops animation or group animations. + * @method stop + * @member tau.animation.SimpleAnimationMixinObject + * @public + */ + stop: function() { + if (!this.simpleAnimation) { + + if (!this.simpleAnimation) { + if (this.length) { + this.simpleAnimation = new ns.SimpleAnimationGroup(this); + } else { + this.simpleAnimation = new ns.SimpleAnimation(this); + } + } + + } + this.simpleAnimation.stop(); + + }, + + /** + * Sets transform property of target. + * @method transform + * @member tau.animation.SimpleAnimationMixinObject + * @public + */ + transform: function(v) { + if (!this.simpleAnimation) { + if (this.length) { + this.simpleAnimation = new ns.SimpleAnimationGroup(this); + } else { + this.simpleAnimation = new ns.SimpleAnimation(this); + } + } + + this.simpleAnimation.target.set(v); + } + }; + + /** + * Makes simpleAnimation for playing animation. + * @constructor SimpleAnimation + * @param {Object} target + * The target is animated by tween animator. + * @member tau.animation.SimpleAnimation + * @private + */ + var SimpleAnimation = function(target) { + + this.tweenAnimator = new ns.TweenAnimator(); + this.target = ObjectManager.getObject(target); // get animation object + this.target.simpleAnimation = this; + + this.target.render && this.tweenAnimator.setRender(this.target.render); + this.target.cur && this.tweenAnimator.setUpdateTarget(this.target.cur); + }; + + /** + * Adds tween information object in animator. + * @method add + * @param {Object} fromTo + * @param {Object} option + * @param {Object} secondTweenAnimator + * @member tau.animation.SimpleAnimation.prototype + * @private + */ + SimpleAnimation.prototype.add = function(fromTo, option, secondTweenAnimator) { + var frame, tweenObject, lastTween, st, + tweenAnimator = secondTweenAnimator || this.tweenAnimator, + self = this; + + if (typeof fromTo === 'string') { + frame = ns.AnimationUtil.effectAnalyzer(this.target, fromTo); + + ns.AnimationUtil.createKeyFrame(frame[0], option, function(ft, o, i) { + if (frame[1] !== undefined) { + o.ease = frame[1][i]; + } + + tweenObject = self.target.createTweenInfo(ft, o, true); + tweenAnimator.add(tweenObject); + + if (frame[2] !== undefined) { + if (i === 0) { + tweenObject.startCallback.on(function() { + self.target.dom.style.webkitTransformOrigin = frame[2]; + }); + } else if (i === frame.length) { + tweenObject.completeCallback.on(function() { + self.target.dom.style.webkitTransformOrigin = ''; + }); + } + } + + if (frame[3] !== undefined) { + tweenObject.completeCallback.on(function() { + self.target.dom.style.visibility = frame[3]; + }); + } + }); + + return; + } + + if (fromTo.effect) { + if (this.parTweensGroup === undefined) { + this.parTweensGroup = []; + st = new ns.TweenAnimator(); + this.parTweensGroup.push(st); + } else { + st = this.parTweensGroup[0]; + } + + this.target.render && st.setRender(this.target.render); + this.target.cur && st.setUpdateTarget(this.target.cur); + + this.add(fromTo.effect, base.deepCopy(option), st); + } + + if (tweenAnimator.getState() === 'running') { + tweenObject = self.target.createTweenInfo(fromTo, option, false); + + if (lastTween = tweenAnimator.getLastTweenInfo()) { + lastTween.completeCallback.on(function() { + self.target.setAnimationFromTo(tweenObject); + }); + } + + } else { + tweenObject = this.target.createTweenInfo(fromTo, option, true); + } + + tweenAnimator.add(tweenObject); + + }; + + /** + * Plays tween animation. + * @method play + * @member tau.animation.SimpleAnimation.prototype + * @private + */ + SimpleAnimation.prototype.play = function() { + var i , len; + this.tweenAnimator.play(); + if (this.parTweensGroup) { + for (i = 0, len = this.parTweensGroup.length; i < len; i++) { + this.parTweensGroup[i].play(); + } + } + }; + + /** + * Stops tween animation. + * @method stop + * @member tau.animation.SimpleAnimation.prototype + * @private + */ + SimpleAnimation.prototype.stop = function() { + var i , len; + this.tweenAnimator.stop(); + if (this.parTweensGroup) { + for (i = 0, len = this.parTweensGroup.length; i < len; i++) { + this.parTweensGroup[i].stop(); + } + } + }; + + /** + * Makes group of simpleAnimation. + * @constructor SimpleGroup + * @param {Array} t + * The target will be added Simple group. + * @member tau.animation.SimpleAnimationGroup + * @private + */ + function SimpleAnimationGroup(t) { + var i, simple; + + this.target = []; + this.len = t.length; + + for (i = 0; i < this.len; i++) { + if (!(simple = ObjectManager.getObject(t[i]).simpleAnimation)) { + this.target[i] = new ns.SimpleAnimation(t[i]); + } else { + this.target[i] = simple; + } + + } + } + + /** + * Adds animation to TweenObject + * @method add + * @param {Object} fromTo + * @param {Object} option + * The target will be added simple group + * @member tau.animation.SimpleGroup.prototype + * @private + */ + SimpleAnimationGroup.prototype.add = function(fromTo, option) { + var completedCnt = 0, + self = this; + + ns.AnimationUtil.checkStagger(this.target, option, function(t, o, idx) { + + if (option.onComplete) { + o.onComplete = function() { + completedCnt++; + if (completedCnt === self.len) { + t.tweenAnimator.getCurrentTweenInfo().completeCallback.on(option.onComplete); + } + }; + } + +// t.simpleAnimation.add(fromTo, o); + t.add(fromTo, o); + + }); + }; + + /** + * Plays animation. + * @method play + * The target will be added simple group + * @member tau.animation.SimpleAnimationGroup.prototype + * @private + */ + SimpleAnimationGroup.prototype.play = function() { + var i; + + for (i = 0; i < this.len; i++) { + this.target[i].play(); + } + }; + + /** + * Stop animation. + * @method play + * The target will be added simple group + * @member tau.animation.SimpleAnimationGroup.prototype + * @private + */ + SimpleAnimationGroup.prototype.stop = function() { + var i; + + for (i = 0; i < this.len; i++) { + this.target[i].stop(); + } + }; + + ns.SimpleAnimation = SimpleAnimation; + ns.SimpleAnimationGroup = SimpleAnimationGroup; + ns.SimpleAnimationMixinObject = SimpleAnimationMixinObject; + +})(window, ns, ns.base); + +/* + * # SimpleMixin + * + * Creates mixin object. + * If user animate pure DOM such as div, SimpleMixin is going to make appropriate target object. + * + * @class ns.SimpleMixin + */ +(function(window, ns) { + 'use strict'; + var SimpleAnimationMixinObject = ns.SimpleAnimationMixinObject; + + /** + * Returns target after mixin APIs. + * @method extendAnimation + * @param {Object} target + * @param {Object|undefined} getElementFn + * @return {Object} + * @member ns.SimpleMixin + * @static + */ + var mixin = function(target, getElementFn) { + var p; + + if (target.prototype !== undefined) { + (p = isProperty(target.prototype)) && throwMixinException(p); + + for (var i in SimpleAnimationMixinObject) { + target.prototype[i] = SimpleAnimationMixinObject[i]; + + } + } else if (target instanceof Object) { + (p = isProperty(target)) && throwMixinException(p); + + for (var i in SimpleAnimationMixinObject) { + if (SimpleAnimationMixinObject.hasOwnProperty(i)) { + target[i] = SimpleAnimationMixinObject[i]; + } + } + } else { + throwMixinException(); + } + return target; + }; + + function isProperty(t) { + var propertyTest = ['tween', 'stop', 'transform', 'simpleAnimation'], + i, len; + + for (i = 0, len = propertyTest.length; i < len; i++) { + if (t.hasOwnProperty(propertyTest[i])) { + return propertyTest[i]; + } + } + + return false; + + } + + function throwMixinException(p) { + var message = 'Function or Object can apply Mixin'; + (p !== undefined) ? (message += ': \"' + p + '\" is overrided.') : (message += '.'); + + console.warn(message); + + //throw "CannotTauAnimationMixinException"; + } + + ns.SimpleMixin = mixin; +})(window, ns); + +(function(window, ns) { + 'use strict'; + + var ObjectManager = ns.ObjectManager.getInstance(); + + /** + * Returns animation target object + * @method target + * @param {String} str + * The str indicate ID or class name for selecting HTML element + * @member ns.Target + * @return {Target} Target Object + * @public + * @class ns.Target + */ + + ns.SimpleMixin(ns.DomObject); + + ns.target = function(str) { + if (typeof str === 'string') { + var s = str.slice(0, 1), c = str.slice(1), + result; + + if (s === '.') { + result = document.getElementsByClassName(c); + if (!result.tween) { // TODO: not mixin + ns.SimpleMixin(result, function() { + return result + }); + } + } else if (s === '#') { + result = document.getElementById(c); + result = ObjectManager.getObject(result); + } else { + + } + } else { + if (str instanceof window.HTMLElement) { + result = ObjectManager.getObject(str); + } else { + + } + } + + return result; + }; + + //checking whether jQuery is loaded or not. + //if (window.jQuery && window.$) { + // ns.SimpleMixin($, $.get); + //} else { + // window.$ = ns.$; + //} + +})(window, ns); + +})(window); \ No newline at end of file diff --git a/d2d_app/client/lib/tau/animation/tau.animation.min.js b/d2d_app/client/lib/tau/animation/tau.animation.min.js new file mode 100644 index 00000000..baba4501 --- /dev/null +++ b/d2d_app/client/lib/tau/animation/tau.animation.min.js @@ -0,0 +1,2 @@ +(function(t){!t.tau&&(t.tau={});var e=t.tau.animation={};(function(t,e){(function(){for(var e=0,i=["ms","moz","webkit","o"],a=0;i.length>a&&!t.requestAnimationFrame;++a)t.requestAnimationFrame=t[i[a]+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i[a]+"CancelAnimationFrame"]||t[i[a]+"CancelRequestAnimationFrame"];void 0===t.requestAnimationFrame&&(t.requestAnimationFrame=function(i){var a=Date.now(),n=Math.max(0,16-(a-e)),r=t.setTimeout(function(){i(a+n)},n);return e=a+n,r}),t.cancelAnimationFrame=t.cancelAnimationFrame||function(e){t.clearTimeout(e)}})(),function(t,e){t.Uint8Array.prototype.setValue=function(){for(var t=0,e=this.length;e>t;t++){if(void 0===arguments[t])return;this[t]=arguments[t]}},e.getTime=function(){return t.performance?t.performance.now?function(){return t.performance.now()}:t.performance.webkitNow?function(){return t.performance.webkitNow()}:function(){return(new Date).getTime()}:function(){return(new Date).getTime()}}()}(t,e);var i={ENUM:{NODETYPE:{GROUP:1,ANIMATION:2},GROUPTYPE:{SEQUENCE:4,PARALLEL:8}},forEach:function(t,e){for(var i=0,a=t&&t.length;a>i;i++){var n=t[i];e(n,i)}},copy:function(t,e){e=e||{};for(var i in t)t.hasOwnProperty(i)&&"$$"!==i.substr(0,2)&&(e[i]=t[i]);return e},arrayCopy:function(t,i){var a,n=t.length;if(void 0!==n)for(void 0===i&&(i=t instanceof Uint8Array?new Uint8Array(n):[]),a=0;n>a;a++)i[a]="string"!=typeof t[a]&&void 0!==t[a].length?e.base.arrayCopy(t[a]):t[a];else i=t;return i},deepCopy:function(t,e){if("object"==typeof t){e=e||{},t.length!==void 0&&(t instanceof Array?e=[]:t instanceof Uint8Array&&(e=new Uint8Array(t.length)));for(var i in t)"object"==typeof t[i]?e[i]=this.deepCopy(t[i]):"string"==typeof t[i]?e[i]=t[i]:"number"==typeof t[i]?e[i]=t[i]:"boolean"==typeof t[i]&&(e[i]=1==t[i]?!0:!1)}else e=t;return e},singleTon:function(t){var e={};return e.getInstance=function(){return void 0===this._singleton&&(this._singleton=new t),this._singleton},e},isNumber:function(t){return"number"==typeof t},isFunction:function(t){return"function"==typeof t},isObject:function(t){return t instanceof Object},isArray:function(t){return t instanceof Array},selector:function(t){var e,i=t.slice(0,1),a=t.slice(1);return"."===i?e=document.getElementsByClassName(a):"#"===i&&(e=document.getElementById(a)),e}};i.WeakMap=function(){this.keys=[],this.values=[],this.i=0},i.WeakMap.prototype.del=function(t){return this.has(t)&&(this.keys.splice(this.i,1),this.values.splice(this.i,1)),this.i>-1},i.WeakMap.prototype.get=function(t,e){return this.has(t)?this.values[this.i]:e},i.WeakMap.prototype.has=function(t){if(t!==Object(t))throw new TypeError("not a non-null object");return this.i=Array.prototype.indexOf.call(this.keys,t),this.i>-1},i.WeakMap.prototype.set=function(t,e){this.has(t)?this.values[this.i]=e:this.values[this.keys.push(t)-1]=e},i.WeakMap.prototype.getKey=function(){return this.keys};var a=!1,n=/xyz/.test(function(){})?/\b_super\b/:/.*/;i.Class=function(){},i.Class.extend=function(t){function e(){return!a&&this._init?this._init.apply(this,arguments):void 0}var i=this.prototype,r=t.static;a=!0;var o=new this;a=!1;for(var s in t)"static"!==s&&(o[s]="function"==typeof t[s]&&"function"==typeof i[s]&&n.test(t[s])?function(t,e){return function(){var a=this._super;this._super=i[t];var n=e.apply(this,arguments);return this._super=a,n}}(s,t[s]):t[s]);if(e.prototype=o,e.prototype.constructor=e,e.extend=arguments.callee,r)for(var c in r)r.hasOwnProperty(c)&&(e[c]=r[c]);return e},e.base=i})(t,e),function(t,e){"use strict";var i=e.base.Class.extend({_init:function(){this.now=e.getTime,this._frameId=null,this.animators=[],this.animatorIdx=0},tickOn:function(){var i=this;(function a(){i._frameId=t.requestAnimationFrame(a);var n,r=e.getTime();for(n=0;i.animatorIdx>n;n++)i.animators[n].tick(r)})()},tickOff:function(){this._frameId&&(t.cancelAnimationFrame(this._frameId),this._frameId=null)},__on:function(t){0>this.animators.indexOf(t)&&(this.animators[this.animatorIdx]=t,this.animatorIdx++,null===this._frameId&&this.tickOn())},__off:function(t){var e=this.animators.indexOf(t);e>=0&&(this.animators.splice(e,1),this.animatorIdx--,0===this.animatorIdx&&this.tickOff())}});e.Ticker=e.base.singleTon(i)}(t,e),function(t,e){"use strict";function i(){this.regExpCubicBezier=/cubic-bezier\s*\(\s*([\d\.]+)\s*,\s*([\d\.]+)\s*,\s*([\d\.]+)\s*,\s*([\d\.]+)\s*\)/}function a(t,e,i,a){return function(t){var i=1-t,n=3*i,r=t*t,o=r*t,s=n*t*i,c=n*r;return s*e+c*a+o}}function n(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}var r;r=i.prototype,r.ease=a(.25,.1,.25,1),r.easeOut=a(0,0,.58,1),r.easeInOut=a(.42,0,.58,1),r.easeIn=a(.42,0,1,1),r.sineIn=a(.47,0,.745,.715),r.sineOut=a(.39,.575,.565,1),r.sineInOut=a(.445,.05,.55,.95),r.expoIn=a(.95,.05,.795,.035),r.expoOut=a(.19,1,.22,1),r.expoInOut=a(1,0,0,1),r.circIn=a(.6,.04,.98,.335),r.circOut=a(.075,.82,.165,1),r.circInOut=a(.785,.135,.15,.86),r.backIn=a(.6,-.28,.735,.045),r.backOut=a(.175,.885,.32,1.275),r.backInOut=a(.68,-.55,.265,1.55),r.zoomInDown=a(.55,.055,.675,.19),r.bounce1=a(.215,.61,.355,1),r.bounce2=a(.755,.05,.855,.06),r.linear=function(t){return t},r.cubicIn=function(t){return t*t*t},r.cubicOut=function(t){return--t*t*t+1},r.cubicInOut=function(t){return.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},r.quadIn=function(t){return t*t},r.quadOut=function(t){return t*(2-t)},r.quadInOut=function(t){return.5>t?2*t*t:-1+(4-2*t)*t},r.quartIn=function(t){return t*t*t*t},r.quartOut=function(t){return 1- --t*t*t*t},r.quartInOut=function(t){return.5>t?8*t*t*t*t:1-8*--t*t*t*t},r.quintIn=function(t){return t*t*t*t*t},r.quintOut=function(t){return 1+--t*t*t*t*t},r.quintInOut=function(t){return.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t},r.bounceOut=function(t){return n(t)},r.bounceIn=function(t){return 1-i.prototype.bounceOut(1-t)},r.bounceInOut=function(t){return.5>t?.5*i.prototype.bounceIn(2*t):.5*i.prototype.bounceOut(2*t-1)+.5};var o=2*Math.PI,s=.3/o*Math.asin(1);r.elasticIn=function(t){return 0===t||1===t?t:-(Math.pow(2,10*(t-=1))*Math.sin((t-s)*o/.3))},r.elasticOut=function(t){return 0===t||1===t?t:Math.pow(2,-10*t)*Math.sin((t-s)*o/.3)+1},r.elasticInOut=function(t){return 1>(t*=2)?-.5*Math.pow(2,10*(t-=1))*Math.sin((t-s)*o/.3):.5*Math.pow(2,-10*(t-=1))*Math.sin((t-s)*o/.3)+1},e.Ease=e.base.singleTon(i)}(t,e),function(t,e){"use strict";var i=e.Ticker.getInstance(),a=e.Ease.getInstance(),n={STOP:"stop",PAUSE:"pause",RUN:"running"},r={FORWARD:!0,REVERSE:!1},o=function(){var t=0,e=0,i=[];return{add:function(t){i[e]=t,e++},next:function(){return e>t?(t++,i[t-1]):!1},cur:function(){return t},rewind:function(){t=0},get:function(t){return void 0===t?i:i[t]},length:function(){return e},hasNext:function(){return e>t},clear:function(){0!==e&&e>=t&&i.splice(0,t),t=0,e=i.length},allClear:function(){i=[],t=e=0}}},s=function(){var t=[],e=0;return{on:function(i){t[e]=i,e++},onFront:function(i){t.unshift(i),e++},emit:function(){for(var i=0;e>i;i++)t[i].apply(null,arguments)},remove:function(i){for(var a=0;e>a;a++)t[a]===i&&(t[a].splice(a,1),e--)},getLength:function(){return e},removeAll:function(){t=[],e=0}}},c=e.base.Class.extend({_init:function(t,e){this.tweenQueue=o(),this.tweenInfo=null,this._direction=r.FORWARD,this._state=n.STOP,this._isTick=!1,this.isTweenInfo=!1,t&&this.add(t,e),this._startTime=this._lastTime=this._playTime=this._previousTime=0,this._totalTime=this._duration+this._delay,this._changedDirection=!1,this._isCache=!1},tick:function(t){if(this._state===n.RUN){var e=t,i=e-this._playTime;if(this._previousTime=e,0>i)return;this._duration>=i?(this.tweenInfo.progress=i/(this._duration||1),this._update()):(1!==this.tweenInfo.progress&&(this.tweenInfo.progress=1,this._update()),e>=this._lastTime&&this._complete())}},play:function(){this._state!==n.RUN&&(this._state===n.PAUSE?(this._direction!==r.FORWARD&&(this._direction=r.FORWARD,this._changedDirection=!0),this.resume()):(this._direction=r.FORWARD,this._play()))},reverse:function(){this._state!==n.RUN&&(this._state===n.PAUSE?(this._direction!==r.REVERSE&&(this._direction=r.REVERSE,this._changedDirection=!0),this.resume()):(this._direction=r.REVERSE,this._play()))},stop:function(){this._state!==n.STOP&&(this._stopTween(),this.tweenQueue.allClear())},pause:function(){this._state===n.RUN&&(this._state=n.PAUSE)},resume:function(t){var i=e.getTime();if(this._state===n.PAUSE){if(this._changedDirection||void 0!==t&&t!==this._direction)void 0!==t&&(this._direction=t),this._lastTime=i+this._previousTime-this._playTime,this._playTime=this._lastTime-this._duration,this._startTime=this._playTime-this._delay,this._changedDirection=!1;else{var a=i-this._previousTime;this._startTime+=a,this._playTime+=a,this._lastTime+=a}this._state=n.RUN}},seek:function(t){var e=t*this._totalTime-this._delay;e>=0&&this._update(e/this._duration)},getSeek:function(t,e){var i,a,n,t,r=this.tweenInfo.name,o=this.tweenInfo.to,s=this.tweenInfo.from;for(e&&(t=t*this._totalTime-this._delay),i=0;a=r[i];i++)this.cur[a]&&(n=this.cur[a].length)?(void 0===this.cur[a]&&(this.cur[a]=[]),this._calculateTween(this.cur[a],o[a],s[a],t)):this.cur[a]=(o[a]-s[a])*this._ease(t)+s[a];return this.cur},setStartTime:function(t){this._startTime=t},replay:function(){this._update(0),this._start()},duration:function(t){this._duration=e.base.isNumber(t)?t:1e3},delay:function(t){this._delay=e.base.isNumber(t)?t:0},ease:function(t){this._ease=e.base.isFunction(a[t])?a[t]:a.linear},loop:function(t){this._loop=e.base.isNumber(t)?t:1},add:function(t,e){var i;return void 0===e?(i=t,i.startCallback=s(),i.completeCallback=s(),i.progress=0):(i={fromTo:{},name:[],progress:0,startCallback:s(),completeCallback:s()},i.option=e),i.option.onStart&&i.startCallback.on(i.option.onStart),i.option.onComplete&&i.completeCallback.on(i.option.onComplete),this.tweenQueue.add(i),1===this.tweenQueue.length()&&(this.tweenQueue.next(),this.initTween(i),this.isTweenInfo=!0),i},setRender:function(t){this.render=t},setUpdateTarget:function(t){this.cur=t},getState:function(){return this._state},getCurrentTweenInfo:function(){return this.tweenInfo},nextTweenInfo:function(){return this.tweenQueue.next()},getLastTweenInfo:function(){return this.tweenQueue.get(this.tweenQueue.length()-1)},getFirstTweenInfo:function(){return this.tweenQueue.get(0)},initTween:function(t){var i=t.option;this.tweenInfo=t,this.cur=void 0!==this.cur?this.cur:void 0!==i._cur?i._cur:{},this.option=i,this._onUpdate=i.onUpdate,e.base.isObject(i)?(this.duration(i.duration),this.ease(i.ease),this.delay(i.delay),this.loop(i.loop),this._reverseDelay=i.reverseDelay||0):(this._duration=1e3,this._delay=0,this._loop=1,this._ease=a.linear,this._reverseDelay=0),this._loopCnt=this._loop},tweenQueueCache:function(t){"boolean"==typeof t&&(this._isCache=t)},_play:function(){this._state===n.PAUSE?this.resume():this._state===n.STOP&&this._start()},_start:function(){this._state=n.RUN,this._startTime=this._startTime||e.getTime(),this._playTime=this._startTime+(this._direction?this._delay:0),this._lastTime=this._playTime+this._duration+(this._direction?0:this._delay)+this._reverseDelay,this.tweenInfo.startCallback.emit(),this._isTick||(i.__on(this),this._isTick=!0)},_update:function(t){var e,i,a,n=this.tweenInfo.name,o=this.tweenInfo.fromTo;for(this.tweenInfo.progress=void 0!==t?t:this._direction===r.REVERSE?1-this.tweenInfo.progress:this.tweenInfo.progress,e=0;i=n[e];e++)o[i][0]&&(a=o[i][0].length)?(void 0===this.cur[i]&&(this.cur[i]=[]),this._calculateTween(this.cur[i],o[i][0],o[i][1])):this.cur[i]=(o[i][1]-o[i][0])*this._ease(this.tweenInfo.progress)+o[i][0];this.render&&this.render.call(this.cur,this.tweenInfo),this._onUpdate&&this._onUpdate.call(this.cur,this.tweenInfo)},_calculateTween:function(t,e,i,a){var n,r;for(void 0===a&&(a=this.tweenInfo.progress),n=0,r=i.length;r>n;n++)"number"==typeof i[n]?t[n]=(i[n]-e[n])*this._ease(a)+e[n]:"string"==typeof i[n]?t[n]=i[n]:(void 0===t[n]&&(t[n]=[]),this._calculateTween(t[n],e[n],i[n]))},_complete:function(){var t;this.setStartTime(null),this.isTweenInfo=!1,this.tweenInfo.completeCallback.emit(),--this._loopCnt>0?this.replay():!this.isTweenInfo&&(t=this.tweenQueue.next())?(this.initTween(t),this._isCache||this.tweenQueue.clear(),this._start()):this.isTweenInfo?this._start():(this._stopTween(),this.option._stackTweensFlag?(this.tweenQueue.rewind(),t=this.tweenQueue.next(),this.initTween(t)):this.tweenQueue.allClear())},_stopTween:function(){this._state=n.STOP,this._startTime=null,i.__off(this),this._isTick=!1}});e.TweenAnimator=e.Tween=c}(t,e),function(t,e,i){"use strict";var a=e.base.Class.extend({_init:function(){this.init()},init:function(){this.translateX=0,this.translateY=0,this.translateZ=0,this.rotateX=0,this.rotateY=0,this.rotateZ=0,this.skewX=0,this.skewY=0,this.scaleX=1,this.scaleY=1},copy:function(t){this.translateX=t.translateX,this.translateY=t.translateY,this.translateZ=t.translateZ,this.rotateX=t.rotateX,this.rotateY=t.rotateY,this.rotateZ=t.rotateZ,this.skewX=t.skewX,this.skewY=t.skewY,this.scaleX=t.scaleX,this.scaleY=t.scaleY},set:function(t){t instanceof Array&&(this.translateX=i.isNumber(t[0])?t[0]:0,this.translateY=i.isNumber(t[1])?t[1]:0,this.translateZ=i.isNumber(t[2])?t[2]:0,this.rotateX=i.isNumber(t[3])?t[3]:0,this.rotateY=i.isNumber(t[4])?t[4]:0,this.rotateZ=i.isNumber(t[5])?t[5]:0,this.scaleX=i.isNumber(t[6])?t[6]:1,this.scaleY=i.isNumber(t[7])?t[7]:1,this.skewX=i.isNumber(t[8])?t[8]:0,this.skewY=i.isNumber(t[9])?t[9]:0)}});e.Transform=a}(t,e,e.base),function(t,e,i){"use strict";var a={aqua:new Uint8Array([0,255,255]),lime:new Uint8Array([0,255,0]),silver:new Uint8Array([192,192,192]),black:new Uint8Array([0,0,0]),maroon:new Uint8Array([128,0,0]),teal:new Uint8Array([0,128,128]),blue:new Uint8Array([0,0,255]),navy:new Uint8Array([0,0,128]),white:new Uint8Array([255,255,255]),fuchsia:new Uint8Array([255,0,255]),olive:new Uint8Array([128,128,0]),yellow:new Uint8Array([255,255,0]),orange:new Uint8Array([255,165,0]),gray:new Uint8Array([128,128,128]),purple:new Uint8Array([128,0,128]),green:new Uint8Array([0,128,0]),red:new Uint8Array([255,0,0]),pink:new Uint8Array([255,192,203]),cyan:new Uint8Array([0,255,255]),transparent:new Uint8Array([255,255,255,0])},n=i.Class.extend({_init:function(){var t=this,e=["borderWidth","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","marginTop","marginRight","marginBottom","marginLeft","paddingTop","paddingRight","paddingBottom","paddingLeft","width","height","top","left","clipTop","clipBottom","clipRight","clipLeft","fontSize","lineHeight"];e.forEach(function(e){t[e]=t._unit.bind(t)});var i=["backgroundPosition","backgroundSize"];i.forEach(function(e){t[e]=t._arrayUnit.bind(t)});var a=["border","borderTop","borderRight","borderLeft","borderBottom"];a.forEach(function(e){t[e]=function(i){var a,n={};return a=t._blank(i),n[e+"Width"]=a[0],n[e+"Style"]="none"===a[1]?"solid":a[1],n[e+"Color"]=a[2],n}});var n=["backgroundColor","color","borderColor","borderTopColor","borderRightColor","borderLeftColor","borderBottomColor"];n.forEach(function(e){t[e]=t._color});var r=["margin","padding"];r.forEach(function(e){t[e]=function(i){var a=t._blank(i),n={};return 4===a.length?(n[e+"Top"]=a[0],n[e+"Right"]=a[1],n[e+"Bottom"]=a[2],n[e+"Left"]=a[3]):3===a.length?(n[e+"Top"]=a[0],n[e+"Right"]=a[1],n[e+"Bottom"]=a[2],n[e+"Left"]=a[1]):2===a.length?(n[e+"Top"]=a[0],n[e+"Right"]=a[1],n[e+"Bottom"]=a[0],n[e+"Left"]=a[1]):1===a.length&&(n[e+"Top"]=a[0],n[e+"Right"]=a[0],n[e+"Bottom"]=a[0],n[e+"Left"]=a[0]),n}});var o=["boxShadow","textShadow"];o.forEach(function(e){t[e]=function(e){var i,a,n,r,o,s=[],c=0,l=/rgb\([0-9]+[\, |\s]+[0-9]+[\, |\s]+[0-9]+\)/g;for(s=e.match(l)||[],e=e.replace(l,"rgb"),e=e.split(","),i=0,n=e.length;n>i;i++){for(e[i].match("rgb")&&s[c]&&(e[i]=e[i].replace("rgb",s[c]),c++),e[i]=t._blank(e[i]),o=e[i].length-1,(r=t._color(e[i][0]))?(e[i].splice(0,1),e[i].push(r)):r=t._color(e[i][o]),a=0;o>a;a++)e[i][a]=t._unit(e[i][a]);e[i][a]=r}return e}})},opacity:function(t){return parseFloat(t)},clip:function(t){var e=t.replace(/\(|\)|,/g," ").trim().split(/\s+/g),i=[];i[0]=e[0];for(var a=1;4>=a;a++)i[a]=this._unit(e[a]);return i},webkitClipPath:function(t){var e,i,a=[],n=t.replace(/\(|\)|,/g," ").trim().split(/\s+/g);for(a.push(n[0]),e=1,i=n.length;i>e;e++)a.push(this._unit(n[e]));return a},backgroundImage:function(t){return t.replace(/url\(|\)$/gi,"")},_arrayUnit:function(t){var e,i,a=t.trim().split(" ");for(e=0,i=a.length;i>e;e++)a[e]=this._unit(a[e]);return a},_unit:function(t){return"string"==typeof t?{number:this._getFloat(t),unit:this._getChar(t)||"px"}:{number:t,unit:"px"}},_color:function(t){var e,i,n,r,o,s,c,l;if(void 0===t||null===t)return console.log("invalid color"),!1;if(a[t])l=a[t];else if(t instanceof Array||t instanceof Uint8Array)l=new Uint8Array(t);else if(c=t.toLowerCase(),c=c.trim(),"r"===c.charAt(0)&&"g"===c.charAt(1)&&"b"===c.charAt(2)){if("a"===c.charAt(3)){for(r=c.replace(/rgba\(/g,"").replace(/\)/g,"").replace(/(\s*)/g,"").replace(/\,/g," ").split(" "),s=0,o=r.length-1;o>s;s++)r[s]=parseInt(r[s]);r[o]=parseFloat(r[o])}else for(r=c.replace(/rgb\(/g,"").replace(/\)/g,"").replace(/(\s*)/g,"").replace(/\,/g," ").split(" "),s=0,o=r.length;o>s;s++)r[s]=parseInt(r[s]);l=new Uint8Array(r)}else{if("#"!==c.charAt(0))return!1;4===c.length&&(e=c.charAt(1),i=c.charAt(2),n=c.charAt(3),c="#"+e+e+i+i+n+n),c=parseInt(c.substr(1),16),l=new Uint8Array(3),l.setValue(c>>16,255&c>>8,255&c)}return l},_getChar:function(t){var e=t.match(/[^0-9.-]/g),i="";return null!==e&&(i=e.join("")),i.replace(/\, /g,""),i},_getNum:function(t){return parseInt(t.match(/^[-]?\d+/g),10)},_getFloat:function(t){return parseFloat(t.match(/^[+-]?\d*(\.?\d*)/g))},_blank:function(t){return t.trim().replace(/\, /g,",").split(" ")}});e.CSSPropertyParser=i.singleTon(n)}(t,e,e.base),function(t,e,i){"use strict";var a=i.Class.extend({_init:function(){this.createColor(),this.createBorderStyle(),this.createBlankFunction(),this.createUnit(),this.createShadow()},opacity:function(t){return t.opacity},WebkitTransform:function(t){var e="";return e+=t.perspective?"perspective("+t.perspective+"px) ":"",e+="translate3d("+t.translateX+"px, "+t.translateY+"px, "+t.translateZ+"px) ",e+=t.rotateX?"rotateX("+t.rotateX+"deg) ":"",e+=t.rotateY?"rotateY("+t.rotateY+"deg) ":"",e+=t.rotateZ?"rotateZ("+t.rotateZ+"deg) ":"",e+=1!==t.scaleX?"scaleX("+t.scaleX+") ":"",e+=1!==t.scaleY?"scaleY("+t.scaleY+") ":"",e+=t.skewX?"skewX("+t.skewX+"deg) ":"",e+=t.skewY?"skewY("+t.skewY+"deg) ":""},createUnit:function(){function t(t,e){return"px"===e[this]?Math.round(t[this])+e[this]:t[this]+e[this]}function e(t,e){return t[this][0]+e[this][0]+" "+t[this][1]+e[this][1]}var i=this,a=["width","height","top","left"],n=["backgroundPosition","backgroundSize"];a.forEach(function(e){i[e]=t.bind(e)}),n.forEach(function(t){i[t]=e.bind(t)})},createColor:function(){var t=this,e=["borderColor","borderTopColor","borderRightColor","borderLeftColor","borderBottomColor","backgroundColor","color"];e.forEach(function(e){t[e]=t._rgbColor(e)})},createBorderStyle:function(){function t(t,e){var i=this+"Width",a=this+"Color",n=this+"Style";return t[i]+e[i]+" "+e[n]+" rgb("+t[a][0]+", "+t[a][1]+", "+t[a][2]+")"}function e(t,e){return t[this].toFixed(2)+e[this]}var i=this,a=["border","borderTop","borderRight","borderLeft","borderBottom"],n=["borderWidth","borderTopWidth","borderRightWidth","borderLeftWidth","borderBottomWidth"],r=["borderStyle","borderTopStyle","borderRightStyle","borderLeftStyle","borderBottomStyle"];a.forEach(function(e){i[e]=t.bind(e)}),r.forEach(function(t){i[t]=i._direct(t)}),n.forEach(function(t){i[t]=e.bind(t)})},createBlankFunction:function(){function t(t,e){var i=this+"Top",a=this+"Right",n=this+"Bottom",r=this+"Left";return t[i]+e[i]+" "+t[a]+e[a]+" "+t[n]+e[n]+" "+t[r]+e[r]}function e(t,e){return t[this]+e[this]}var i=this,a=["margin","padding"],n=["marginTop","marginRight","marginBottom","marginLeft","paddingTop","paddingRight","paddingBottom","paddingLeft","lineHeight","fontSize"];a.forEach(function(e){i[e]=t.bind(e)}),n.forEach(function(t){i[t]=e.bind(t)})},createShadow:function(){var t=this,e=["boxShadow","textShadow"];e.forEach(function(e){t[e]=function(t,i){var a,n,r,o,s=t[e],c=i[e],l="";for(a=0,r=s.length;r>a;a++){for(0!==a&&(l+=", "),n=0,o=s[a].length-1;o>n;n++)l+=s[a][n]+c[a][n]+" ";l+="rgb("+s[a][n][0]+","+s[a][n][1]+","+s[a][n][2]+") "}return l}})},clip:function(t){return t.clip[0]+"("+t.clip[1][0]+t.clip[1][1]+" "+t.clip[2][0]+t.clip[2][1]+" "+t.clip[3][0]+t.clip[3][1]+" "+t.clip[4][0]+t.clip[4][1]+")"},webkitClipPath:function(t,e){var i,a,n,r=t.webkitClipPath,o=e.webkitClipPath,s=e.webkitClipPathStyle;if("circle"===s)return o[0]+"("+r[0]+o[1]+" at "+r[1]+o[2]+" "+r[2]+o[3]+")";if("polygon"===s){for(n=s+"(",i=0,a=r.length;a>i;i+=2)n+=r[i]+o[i]+" "+r[i+1]+o[i+1],n+=i+1!==a-1?", ":")";return n}},_direct:function(t){return function(e){return e[t]}},_rgbColor:function(t){return function(e){return"rgb("+e[t][0]+", "+e[t][1]+", "+e[t][2]+")"}}});e.CssStringCreator=i.singleTon(a)}(t,e,e.base),function(t,e,i){"use strict";var a=e.CSSPropertyParser.getInstance(),n=i.Class.extend({_init:function(){var t,e,i,n,r,o,s,c=this;t=["backgroundColor","color","borderColor","borderTopColor","borderRightColor","borderLeftColor","borderBottomColor"],t.forEach(function(t){c[t]=function(e){c.settingCssAnimation(t,e,"_colorType")}}),e=["width","left","marginRight","marginLeft","paddingRight","paddingLeft","marginTop","marginBottom","paddingBottom","paddingTop","clipTop","clipBottom","clipRight","clipLeft","borderWidth","borderTopWidth","borderRightWidth","borderLeftWidth","borderBottomWidth","clipTop","clipBottom","clipRight","clipLeft"],e.forEach(function(t){c[t]=function(e){c.settingCssAnimation(t,e,"_unitType","width")}}),i=["height","top"],i.forEach(function(t){c[t]=function(e){c.settingCssAnimation(t,e,"_unitType","height")}}),n=["backgroundPosition","backgroundSize"],n.forEach(function(t){c[t]=function(e){c.settingCssAnimation(t,e,"_backgroundType")}}),r=["margin","padding"],r.forEach(function(t){c[t]=function(e){var i,n,r;if(2===e.animationFromTo[t].length){i=a[t](e.animationFromTo[t][0]),n=a[t](e.animationFromTo[t][1]);for(r in n)e.animationFromTo[r]=[i[r],n[r]],c[r](e)}else{n=a[t](e.animationFromTo[t]);for(r in n)e.animationFromTo[r]=n[r],c[r](e)}}}),o=["border","borderTop","borderRight","borderLeft","borderBottom"],o.forEach(function(t){c[t]=function(e){var i,n;2===e.animationFromTo[t].length?(i=a[t](e.animationFromTo[t][0]),n=a[t](e.animationFromTo[t][1]),e.animationFromTo[t+"Width"]=[i[t+"Width"],n[t+"Width"]],e.animationFromTo[t+"Color"]=[i[t+"Color"],n[t+"Color"]]):(n=a[t](e.animationFromTo[t]),e.animationFromTo[t+"Width"]=n[t+"Width"],e.animationFromTo[t+"Color"]=n[t+"Color"]),e.unit[t+"Style"]=n[t+"Style"],c[t+"Width"](e),c[t+"Color"](e)}}),o=["border","borderTop","borderRight","borderLeft","borderBottom"],o.forEach(function(t){c[t]=function(e){var i,n;2===e.animationFromTo[t].length?(i=a[t](e.animationFromTo[t][0]),n=a[t](e.animationFromTo[t][1]),e.animationFromTo[t+"Width"]=[i[t+"Width"],n[t+"Width"]],e.animationFromTo[t+"Color"]=[i[t+"Color"],n[t+"Color"]]):(n=a[t](e.animationFromTo[t]),e.animationFromTo[t+"Width"]=n[t+"Width"],e.animationFromTo[t+"Color"]=n[t+"Color"]),e.unit[t+"Style"]=n[t+"Style"],c[t+"Width"](e),c[t+"Color"](e)}}),s=["boxShadow","textShadow"],s.forEach(function(t){c[t]=function(e){c.settingCssAnimation(t,e,"_shadowType")}}),this.webkitClipPath=function(t){this.settingCssAnimation("webkitClipPath",t,"_webkitClipPathType")},this.fontSize=function(t){this.settingCssAnimation("fontSize",t,"_fontSizeType")},this.lineHeight=function(t){this.settingCssAnimation("lineHeight",t,"_unitType","lineHeight")},this.opacity=function(t){this.settingCssAnimation("opacity",t)},this.WebkitTransform=function(t,e){var i,a;"object"==typeof e.animationFromTo[t]&&2===e.animationFromTo[t].length?(i=e.animationFromTo[t][0],a=e.animationFromTo[t][1]):(i=e.target.cur[t],a=e.animationFromTo[t]),("translateX"===t||"translateY"===t||"translateZ"===t)&&("string"==typeof i&&(i=this._getTranslateValue(t,e,i)),"string"==typeof a&&(a=this._getTranslateValue(t,e,a))),e.fromTo[t]=[i,a],e.target.from[t]=a,e.name.push(t)}},settingCssAnimation:function(e,i,n,r){var o;o=i.fromTo[e]=[],"object"==typeof i.animationFromTo[e]&&2===i.animationFromTo[e].length?(o[0]=i.animationFromTo[e][0],o[1]=i.animationFromTo[e][1]):(o[0]=t.getComputedStyle(i.target.dom)[e],(""===o[0]||"auto"===o[0]||"none"===o[0]||void 0===o[0])&&(o[0]=this._exceptGetStyle(i.target.dom,e)),o[1]=i.animationFromTo[e]),o[0]=a[e](o[0]),o[1]=a[e](o[1]),n&&this[n]&&this[n](e,i,r),i.name.push(e)},unitArray:function(t,e,i){var a,n,r,o,s,c=[],l=[],u=[],p=e.fromTo[t];for(a=0,n=p[0].length;n>a;a++)r=p[0][a],o=p[1][a],r.unit!==o.unit&&(s="object"==typeof i&&i[a]?i[a]:i,this._convertUnit(e.target.dom,r,o,s,t)),c.push(r.number),l.push(o.number),u.push(o.unit);e.fromTo[t]=[c,l],e.unit[t]=u},_colorType:function(t,e){e.target.cur[t]=new Uint8Array(3)},_fontSizeType:function(t,e){var i=e.fromTo[t];isNaN(i[0].number)&&this._getStringFontNumber(i[0],e.target.dom),isNaN(i[1].number)&&this._getStringFontNumber(i[1],e.target.dom),this._unitType(t,e,"fontSize")},_backgroundType:function(t,e){1===e.fromTo[t][0].length&&e.fromTo[t][0].push({number:50,unit:"%"}),1===e.fromTo[t][1].length&&e.fromTo[t][1].push({number:50,unit:"%"}),this.unitArray(t,e,["width","height"])},_unitType:function(t,e,i){var a=e.fromTo[t][0],n=e.fromTo[t][1];return a.unit!==n.unit&&this._convertUnit(e.target.dom,a,n,i,t),e.unit[t]=n.unit,e.target.unit[t]=n.unit,e.fromTo[t][0]=a.number,e.fromTo[t][1]=n.number,!1},_webkitClipPathType:function(t,e){var i=e.fromTo[t];e.unit[t+"Style"]=i[1][0],i[0].splice(0,1),i[1].splice(0,1),this.unitArray(t,e,"width")},_shadowType:function(t,e){var a,n,r,o,s,c,l,u=e.fromTo[t][0],p=e.fromTo[t][1],h=[];for(e.unit[t]=h,o=0,l=p.length;l>o;o++){for(!u[o]&&(u[o]=[]),a=u[o],n=p[o],r=[],h.push(r),s=0,c=n.length-1;c>s;s++)r.push(n[s].unit),a[s]&&n[s].unit!==a[s].unit&&this._convertUnit(e.target.dom,a[s],n[s],"width",t),n[s]=n[s].number,a[s]=a[s]?a[s].number:0;a[c]||(a[c]=new Uint8Array(3))}e.cur[t]=i.deepCopy(p)},_exceptGetStyle:function(e,i){var a,n,r;return"left"===i?a=e.offsetLeft+"px":"top"===i?a=e.offsetTop+"px":"clip"===i?a="rect(0px 0px 0px 0px)":"boxShadow"===i?a="0px 0px 0px 0px black":"textShadow"===i?a="0px 0px 0px black":"backgroundPosition"===i?a="0px 0px":"backgroundSize"===i&&(n=this._getStyle(e,"backgroundImage"),t.aa=r=new Image,r.src=n,a=r.width&&r.height?r.width+"px "+r.height+"px":"0px 0px"),void 0===a&&(a="0px"),a},_getCriterionEm:function(t,e){return"fontSize"===e?16:this._getStyle(t,"fontSize").number||16},_getCriterionPercent:function(e,i,n){var r,o,s,c,l=e.parentNode;if("lineHeight"===n)return this._getStyle(e,"fontSize").number||16;if("backgroundPosition"===n)return s=this._getStyle(e,i).number,c=this._getBackgroundImageSize(e,i),s-c+1;if("backgroundSize"===n)return this._getStyle(e,i).number;for(r=a._getFloat(t.getComputedStyle(l)[i]);""===r&&l!==document.body;)l=l.parentNode,r=a._getFloat(t.getComputedStyle(l)[i]);return 0!==r||"width"!==i&&"height"!==i||(o=i.substring(0,1).toUpperCase()+i.substring(1),r=t["inner"+o]),r},_getStyle:function(e,i){var n=t.getComputedStyle(e)[i];return n=a[i](n)},_getBackgroundImageSize:function(t,e){var i,a,n=this._getStyle(t,"backgroundSize");return"auto"===n[0].unit?(i=this._getStyle(t,"backgroundImage"),a=new Image,a.src=i,void 0===e?[a.width,a.height]:a[e]):n["width"===e?0:1].number},_getStringFontNumber:function(t,e){var i=t.unit;"normal"===i||"initial"===i?(t.number=this._getStyle(e,"fontSize").number||16,t.unit="px"):"xx-small"===i?(t.number=.5625,t.unit="em"):"x-small"===i?(t.number=.625,t.unit="em"):"small"===i?(t.number=.8125,t.unit="em"):"medium"===i?(t.number=1,t.unit="em"):"large"===i?(t.number=1.125,t.unit="em"):"x-large"===i?(t.number=1.5,t.unit="em"):"xx-large"===i&&(t.number=2,t.unit="em")},_getTranslateValue:function(t,e,i){var n,r;return n=a._unit(i),"px"!==n.unit?"translateX"===t||"translateZ"===t?r=this._convertPx(e.target.dom,n.number,n.unit,"width"):"translateY"===t&&(r=this._convertPx(e.target.dom,n.number,n.unit,"height")):r=n.number,r},_convertUnit:function(t,e,i,a,n){"em"===i.unit?e.number=this._convertEm(t,e.number,e.unit,a,n):"%"===i.unit?e.number=this._convertPer(t,e.number,e.unit,a,n):"px"===i.unit?e.number=this._convertPx(t,e.number,e.unit,a,n):"cm"===i.unit?e.number=this._convertCm(t,e.number,e.unit,a,n):"pt"===i.unit&&(e.number=this._convertPt(t,e.number,e.unit,a,n))},_convertEm:function(t,e,i,a,n){var r=this._getCriterionEm(t,a,n);return 0===e?0:"px"===i?e/r:"%"===i?e/100*this._getCriterionPercent(t,a,n)/r:"cm"===i||"pt"===i?this._convertPx(t,e,i,a,n)/r:!1},_convertPer:function(t,e,i,a,n){var r=this._getCriterionPercent(t,a,n);return 0===e?0:"px"===i?100*(e/r):"em"===i?100*(e*this._getCriterionEm(t,a,n)/r):"cm"===i||"pt"===i?100*(this._convertPx(t,e,i,a,n)/r):!1},_convertPx:function(t,e,i,a,n){return 0===e?0:"%"===i?e/100*this._getCriterionPercent(t,a,n):"em"===i?e*e*this._getCriterionEm(t,a,n):"cm"===i?37.795*e:"pt"===i?1.3*e:!1},_convertCm:function(t,e,i,a,n){var r;return 0===e?0:(r="px"!==i?this._convertPx(t,e,i,a,n):e,.02646*r)},_convertPt:function(t,e,i,a,n){var r;return 0===e?0:(r="px"!==i?this._convertPx(t,e,i,a,n):e,.75*r)}});e.CssAnimationUtil=e.base.singleTon(n)}(t,e,e.base),function(t,e){var i={optionAnalyzer:function(t,e){var i;return void 0!==t?"number"==typeof t?(i=e&&"object"==typeof e?e:{},i.duration=t):"object"==typeof t&&(i=t):(i={},i.duration=1e3),i},checkStagger:function(t,i,a){var n,r,o;for(this.animations=[],n=0,r=t.length;r>n;n++)o=e.base.deepCopy(i),i.stagger&&(o.delay=i.stagger*n+(i.delay||0),o.reverseDelay=i.stagger*(r-n)),0!==n&&i.drag&&(o.duration+=i.drag*n),0===n&&i.onStart&&(o.onStart=i.onStart),a(t[n],o,n)},createKeyFrame:function(t,i,a){var n,r,o,s,c,l,u=[];for(n in t)u.push(parseFloat(n));for(u.sort(function(t,e){return t-e}),s=u[0],n=0,o=u.length-1;o>n;n++){l=e.base.deepCopy(i),c={};for(r in t[u[n+1]])c[r]=void 0!==t[u[n]][r]?[t[u[n]][r],t[u[n+1]][r]]:t[u[n+1]][r];l.duration=i.duration*(u[n+1]-s),s=u[n+1],0===n?(i.onStart&&(l.onStart=i.onStart),i.delay&&(l.delay=i.delay),l.reverseDelay=0):(i.delay&&(l.delay=0),i.stagger&&(l.delay=0),n===o-1?i.onComplete&&(l.onComplete=i.onComplete):l.reverseDelay=0),a(c,l,n)}},effectAnalyzer:function(t,i){var a,n,r,o,s,c=e.CssAnimationUtil.getInstance()._getCriterionPercent(t.dom,"width"),l=e.CssAnimationUtil.getInstance()._getCriterionPercent(t.dom,"height");if(a=i,t.dom.style.opacity=t.dom.style.opacity?t.dom.style.opacity:1,"pulse"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY},.5:{scaleX:1.05*t.cur.scaleX,scaleY:1.05*t.cur.scaleY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY}};else if("rollIn"===a)n={0:{translateX:-100+t.cur.translateX,rotateZ:-120+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{translateX:0+t.cur.translateX,rotateZ:0+t.cur.rotateZ,opacity:1*t.dom.style.opacity}};else if("rollOut"===a)n={0:{opacity:1*t.dom.style.opacity},1:{translateX:200+t.cur.translateX,rotateZ:120+t.cur.rotateZ,opacity:0*t.dom.style.opacity}};else if("bounce"===a)n={0:{translateY:0+t.cur.translateY},.2:{translateY:0+t.cur.translateY},.4:{translateY:-30+t.cur.translateY},.5:{translateY:0+t.cur.translateY},.7:{translateY:-15+t.cur.translateY},.8:{translateY:0+t.cur.translateY},.9:{translateY:-4+t.cur.translateY},1:{translateY:0+t.cur.translateY}},r=["bounce1","bounce1","bounce2","bounce1","bounce2","bounce1","","bounce1"],o="center bottom";else if("bounceIn"===a)n={0:{scaleX:.3*t.cur.scaleX,scaleY:.3*t.cur.scaleY},.2:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY},.4:{scaleX:.9*t.cur.scaleX,scaleY:.9*t.cur.scaleY},.6:{scaleX:1.03*t.cur.scaleX,scaleY:1.03*t.cur.scaleY},.8:{scaleX:.97*t.cur.scaleX,scaleY:.97*t.cur.scaleY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY}},r=["bounce1","bounce1","bounce1","bounce1","bounce1","bounce1"]; +else if("bounceInDown"===a)n={0:{translateY:-3e3+t.cur.translateY,opacity:0*t.dom.style.opacity},.6:{translateY:25+t.cur.translateY,opacity:1*t.dom.style.opacity},.75:{translateY:-10+t.cur.translateY,opacity:1*t.dom.style.opacity},.9:{translateY:5+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity}},r=["bounce1","bounce1","bounce1","bounce1","bounce1"];else if("bounceInLeft"===a)n={0:{translateX:-3e3+t.cur.translateX,opacity:0*t.dom.style.opacity},.6:{translateX:25+t.cur.translateX,opacity:1*t.dom.style.opacity},.75:{translateX:-10+t.cur.translateX,opacity:1*t.dom.style.opacity},.9:{translateX:5+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity}},r=["bounce1","bounce1","bounce1","bounce1","bounce1"];else if("bounceInRight"===a)n={0:{translateX:3e3+t.cur.translateX,opacity:0*t.dom.style.opacity},.6:{translateX:-25+t.cur.translateX,opacity:1*t.dom.style.opacity},.75:{translateX:10+t.cur.translateX,opacity:1*t.dom.style.opacity},.9:{translateX:-5+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity}},r=["bounce1","bounce1","bounce1","bounce1","bounce1"];else if("bounceInUp"===a)n={0:{translateY:3e3+t.cur.translateY,opacity:0*t.dom.style.opacity},.6:{translateY:-25+t.cur.translateY,opacity:1*t.dom.style.opacity},.75:{translateY:10+t.cur.translateY,opacity:1*t.dom.style.opacity},.9:{translateY:-5+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity}},r=["bounce1","bounce1","bounce1","bounce1","bounce1"];else if("bounceOut"===a)n={.2:{opacity:0*t.dom.style.opacity,scaleX:.9*t.cur.scaleX,scaleY:.9*t.cur.scaleY},.5:{opacity:1*t.dom.style.opacity,scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY},1:{opacity:0*t.dom.style.opacity,scaleX:.3*t.cur.scaleX,scaleY:.3*t.cur.scaleY}};else if("bounceOutDown"===a)n={0:{translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity},.1:{translateY:10+t.cur.translateY,opacity:1*t.dom.style.opacity},.45:{translateY:-20+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{translateY:2e3+t.cur.translateY,opacity:0*t.dom.style.opacity}};else if("bounceOutLeft"===a)n={0:{translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity},.2:{translateX:20+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{translateX:-2e3+t.cur.translateX,opacity:0*t.dom.style.opacity}};else if("bounceOutRight"===a)n={0:{translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity},.2:{translateX:-20+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{translateX:2e3+t.cur.translateX,opacity:0*t.dom.style.opacity}};else if("bounceOutUp"===a)n={0:{translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity},.2:{translateY:-10+t.cur.translateY,opacity:1*t.dom.style.opacity},.45:{translateY:20+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{translateY:-2e3+t.cur.translateY,opacity:0*t.dom.style.opacity}};else if("zoomIn"===a)n={0:{scaleX:.3*t.cur.scaleX,scaleY:.3*t.cur.scaleY,opacity:0*t.dom.style.opacity},.5:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,opacity:1*t.dom.style.opacity}};else if("zoomInDown"===a)n={0:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,opacity:0*t.dom.style.opacity,translateX:0+t.cur.translateX,translateY:-1e3+t.cur.translateY},.6:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX,translateY:60+t.cur.translateY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX,translateY:0+t.cur.translateY}},r=["zoomInDown","backOut"];else if("zoomInLeft"===a)n={0:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,opacity:0*t.dom.style.opacity,translateX:-1e3+t.cur.translateX},.6:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateX:10+t.cur.translateX},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateX}},r=["zoomInDown","backOut"];else if("zoomInRight"===a)n={0:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,opacity:0*t.dom.style.opacity,translateX:1e3+t.cur.translateX,translateY:t.cur.translateY},.6:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateX:-10+t.cur.translateX,translateY:t.cur.translateY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateY:t.cur.translateY}},r=["zoomInDown","backOut"];else if("zoomInUp"===a)n={0:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,opacity:0*t.dom.style.opacity,translateY:1e3+t.cur.translateY},.6:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateY:-60+t.cur.translateY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY}},r=["zoomInDown","backOut"];else if("zoomOut"===a)n={0:{opacity:1*t.dom.style.opacity},.6:{scaleX:.3*t.cur.scaleX,scaleY:.3*t.cur.scaleY,opacity:0*t.dom.style.opacity},1:{opacity:0*t.dom.style.opacity}};else if("zoomOutDown"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity},.4:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,translateY:-60+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,translateY:2e3+t.cur.translateY,opacity:0*t.dom.style.opacity}},r=["zoomInDown","backOut"],o="center bottom";else if("zoomOutLeft"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity},.4:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,translateX:42+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,translateX:-2e3+t.cur.translateX,opacity:0*t.dom.style.opacity}},o="left center";else if("zoomOutRight"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,translateX:0+t.cur.translateX,opacity:1*t.dom.style.opacity},.4:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,translateX:-42+t.cur.translateX,opacity:1*t.dom.style.opacity},1:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,translateX:2e3+t.cur.translateX,opacity:0*t.dom.style.opacity}},o="right center";else if("zoomOutUp"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity},.4:{scaleX:.475*t.cur.scaleX,scaleY:.475*t.cur.scaleY,translateY:60+t.cur.translateY,opacity:1*t.dom.style.opacity},1:{scaleX:.1*t.cur.scaleX,scaleY:.1*t.cur.scaleY,translateY:-2e3+t.cur.translateY,opacity:0*t.dom.style.opacity}},r=["zoomInDown","backOut"],o="center bottom";else if("slideInDown"===a)n={0:{translateY:-1*l+t.cur.translateY},1:{translateY:0+t.cur.translateY}},s="visible";else if("slideInLeft"===a)n={0:{translateX:-1*c+t.cur.translateX},1:{translateX:0+t.cur.translateX}},s="visible";else if("slideInRight"===a)n={0:{translateX:1*c+t.cur.translateX},1:{translateX:0+t.cur.translateX}},s="visible";else if("slideInUp"===a)n={0:{translateY:1*l+t.cur.translateY},1:{translateY:0+t.cur.translateY}},s="visible";else if("slideOutDown"===a)n={0:{translateY:0+t.cur.translateY},1:{translateY:1*l+t.cur.translateY}},s="hidden";else if("slideOutLeft"===a)n={0:{translateX:0+t.cur.translateX},1:{translateX:-1*c+t.cur.translateX}},s="hidden";else if("slideOutRight"===a)n={0:{translateX:0+t.cur.translateX},1:{translateX:1*c+t.cur.translateX}},s="hidden";else if("slideOutUp"===a)n={0:{translateY:0+t.cur.translateY},1:{translateY:-1*l+t.cur.translateY}},s="hidden";else if("flash"===a)n={0:{opacity:1*t.dom.style.opacity},.25:{opacity:0*t.dom.style.opacity},.5:{opacity:1*t.dom.style.opacity},.75:{opacity:0*t.dom.style.opacity},1:{opacity:1*t.dom.style.opacity}};else if("rubberBand"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY},.3:{scaleX:1.25*t.cur.scaleX,scaleY:.75*t.cur.scaleY},.4:{scaleX:.75*t.cur.scaleX,scaleY:1.25*t.cur.scaleY},.5:{scaleX:1.15*t.cur.scaleX,scaleY:.85*t.cur.scaleY},.65:{scaleX:.95*t.cur.scaleX,scaleY:1.05*t.cur.scaleY},.75:{scaleX:1.05*t.cur.scaleX,scaleY:.95*t.cur.scaleY},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY}};else if("shake"===a)n={0:{translateX:0+t.cur.translateX},.1:{translateX:-10+t.cur.translateX},.2:{translateX:10+t.cur.translateX},.3:{translateX:-10+t.cur.translateX},.4:{translateX:10+t.cur.translateX},.5:{translateX:-10+t.cur.translateX},.6:{translateX:10+t.cur.translateX},.7:{translateX:-10+t.cur.translateX},.8:{translateX:10+t.cur.translateX},.9:{translateX:-10+t.cur.translateX},1:{translateX:0+t.cur.translateX}};else if("swing"===a)n={0:{rotateZ:0+t.cur.rotateZ},.2:{rotateZ:15+t.cur.rotateZ},.4:{rotateZ:-10+t.cur.rotateZ},.6:{rotateZ:5+t.cur.rotateZ},.8:{rotateZ:-5+t.cur.rotateZ},1:{rotateZ:0+t.cur.rotateZ}},o="top center";else if("tada"===a)n={0:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,rotateZ:0+t.cur.rotateZ},.15:{scaleX:.9*t.cur.scaleX,scaleY:.9*t.cur.scaleY,rotateZ:-3+t.cur.rotateZ},.3:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:3+t.cur.rotateZ},.4:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:-3+t.cur.rotateZ},.5:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:3+t.cur.rotateZ},.6:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:-3+t.cur.rotateZ},.7:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:3+t.cur.rotateZ},.8:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:-3+t.cur.rotateZ},.9:{scaleX:1.1*t.cur.scaleX,scaleY:1.1*t.cur.scaleY,rotateZ:3+t.cur.rotateZ},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,rotateZ:0+t.cur.rotateZ}};else if("wobble"===a)n={0:{translateX:0+t.cur.translateX,rotateZ:0+t.cur.rotateZ},.15:{translateX:c*-.25+t.cur.translateX,rotateZ:-5+t.cur.rotateZ},.3:{translateX:.2*c+t.cur.translateX,rotateZ:3+t.cur.rotateZ},.45:{translateX:c*-.15+t.cur.translateX,rotateZ:-3+t.cur.rotateZ},.6:{translateX:.1*c+t.cur.translateX,rotateZ:2+t.cur.rotateZ},.75:{translateX:c*-.05+t.cur.translateX,rotateZ:-1+t.cur.rotateZ},1:{translateX:0+t.cur.translateX,rotateZ:0+t.cur.rotateZ}};else if("jello"===a)n={0:{skewX:0+t.cur.skewX,skewY:0+t.cur.skewY},.22:{skewX:-12.5+t.cur.skewX,skewY:-12.5+t.cur.skewY},.33:{skewX:6.25+t.cur.skewX,skewY:6.25+t.cur.skewY},.44:{skewX:-3.125+t.cur.skewX,skewY:-3.125+t.cur.skewY},.55:{skewX:1.5625+t.cur.skewX,skewY:1.5625+t.cur.skewY},.66:{skewX:-.78125+t.cur.skewX,skewY:-.78125+t.cur.skewY},.77:{skewX:.390625+t.cur.skewX,skewY:.390625+t.cur.skewY},.88:{skewX:-.1953125+t.cur.skewX,skewY:-.1953125+t.cur.skewY},1:{skewX:0+t.cur.skewX,skewY:0+t.cur.skewY}},o="center";else if("fadeIn"===a)n={0:{opacity:0*t.dom.style.opacity},1:{opacity:1*t.dom.style.opacity}};else if("fadeInDown"===a)n={0:{translateY:-1*l+t.cur.translateY,opacity:0*t.dom.style.opacity},1:{translateY:0+t.cur.translateY,opacity:1*t.dom.style.opacity}};else if("fadeInDownBig"===a)n={0:{opacity:0*t.dom.style.opacity,translateY:-2e3+t.cur.translateY},1:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY}};else if("fadeInLeft"===a)n={0:{opacity:0*t.dom.style.opacity,translateX:-1*c+t.cur.translateX},1:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX}};else if("fadeInLeftBig"===a)n={0:{opacity:0*t.dom.style.opacity,translateX:-2e3+t.cur.translateX},1:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX}};else if("fadeInRight"===a)n={0:{opacity:0*t.dom.style.opacity,translateX:1*c+t.cur.translateX},1:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX}};else if("fadeInRightBig"===a)n={0:{opacity:0*t.dom.style.opacity,translateX:2e3+t.cur.translateX},1:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX}};else if("fadeInUp"===a)n={0:{opacity:0*t.dom.style.opacity,translateY:1*l+t.cur.translateY},1:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY}};else if("fadeInUpBig"===a)n={0:{opacity:0*t.dom.style.opacity,translateY:2e3+t.cur.translateY},1:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY}};else if("fadeOut"===a)n={0:{opacity:1*t.dom.style.opacity},1:{opacity:0*t.dom.style.opacity}};else if("fadeOutDown"===a)n={0:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY},1:{opacity:0*t.dom.style.opacity,translateY:1*l+t.cur.translateY}};else if("fadeOutDownBig"===a)n={0:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY},1:{opacity:0*t.dom.style.opacity,translateY:2e3+t.cur.translateY}};else if("fadeOutLeft"===a)n={0:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX},1:{opacity:0*t.dom.style.opacity,translateX:-1*c+t.cur.translateX}};else if("fadeOutLeftBig"===a)n={0:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX},1:{opacity:0*t.dom.style.opacity,translateX:-2e3+t.cur.translateX}};else if("fadeOutRight"===a)n={0:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX},1:{opacity:0*t.dom.style.opacity,translateX:1*c+t.cur.translateX}};else if("fadeOutRightBig"===a)n={0:{opacity:1*t.dom.style.opacity,translateX:0+t.cur.translateX},1:{opacity:0*t.dom.style.opacity,translateX:2e3+t.cur.translateX}};else if("fadeOutUp"===a)n={0:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY},1:{opacity:0*t.dom.style.opacity,translateY:-1*l+t.cur.translateY}};else if("fadeOutUpBig"===a)n={0:{opacity:1*t.dom.style.opacity,translateY:0+t.cur.translateY},1:{opacity:0*t.dom.style.opacity,translateY:-2e3+t.cur.translateY}};else if("flip"===a)n={0:{rotateY:-360+t.cur.rotateY,perspective:400},.4:{rotateY:-190+t.cur.rotateY,translateZ:150+t.cur.translateZ,perspective:400},.5:{rotateY:-170+t.cur.rotateY,translateZ:150+t.cur.translateZ,perspective:400},.8:{scaleX:.95*t.cur.scaleX,scaleY:.95*t.cur.scaleY,perspective:400},1:{scaleX:1*t.cur.scaleX,scaleY:1*t.cur.scaleY,rotateY:0+t.cur.rotateY,translateZ:0+t.cur.translateZ,perspective:400}},r=["easeIn","easeIn","easeIn","easeIn","easeIn"];else if("flipInX"===a)n={0:{rotateX:90+t.cur.rotateX,perspective:400,opacity:0*t.dom.style.opacity},.4:{rotateX:-20+t.cur.rotateX,perspective:400,opacity:1*t.dom.style.opacity},.6:{rotateX:10+t.cur.rotateX,perspective:400,opacity:1*t.dom.style.opacity},.8:{rotateX:-5+t.cur.rotateX,perspective:400,opacity:1*t.dom.style.opacity},1:{rotateX:0+t.cur.rotateX,perspective:400,opacity:1*t.dom.style.opacity}},r=["easeIn","easeIn","easeIn","easeIn","easeIn"];else if("flipInY"===a)n={0:{rotateY:90+t.cur.rotateY,perspective:400,opacity:0*t.dom.style.opacity},.4:{rotateY:-20+t.cur.rotateY,perspective:400,opacity:1*t.dom.style.opacity},.6:{rotateY:10+t.cur.rotateY,perspective:400,opacity:1*t.dom.style.opacity},.8:{rotateY:-5+t.cur.rotateY,perspective:400,opacity:1*t.dom.style.opacity},1:{rotateY:0+t.cur.rotateY,perspective:400,opacity:1*t.dom.style.opacity}},r=["easeIn","easeIn","easeIn","easeIn","easeIn"];else if("flipOutX"===a)n={0:{perspective:400},.3:{perspective:400,rotateX:-20+t.cur.rotateX,opacity:1*t.dom.style.opacity},1:{perspective:400,rotateX:90+t.cur.rotateX,opacity:0*t.dom.style.opacity}};else if("flipOutY"===a)n={0:{perspective:400},.3:{perspective:400,rotateY:-15+t.cur.rotateY,opacity:1*t.dom.style.opacity},1:{perspective:400,rotateY:90+t.cur.rotateY,opacity:0*t.dom.style.opacity}};else if("lightSpeedIn"===a)n={0:{translateX:1*c+t.cur.translateX,skewX:-30+t.cur.skewX,opacity:0*t.dom.style.opacity},.6:{translateX:0+t.cur.translateX,skewX:20+t.cur.skewX,opacity:1*t.dom.style.opacity},.8:{translateX:0+t.cur.translateX,skewX:-5+t.cur.skewX,opacity:1*t.dom.style.opacity},1:{translateX:0+t.cur.translateX,skewX:0+t.cur.skewX,opacity:1*t.dom.style.opacity}};else if("lightSpeedOut"===a)n={0:{opacity:1*t.dom.style.opacity},1:{translateX:1*c+t.cur.translateX,skewX:30+t.cur.skewX,opacity:0*t.dom.style.opacity}};else if("rotateIn"===a)n={0:{rotateZ:-200+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{rotateZ:0+t.cur.rotateZ,opacity:1*t.dom.style.opacity}},o="center";else if("rotateInDownLeft"===a)n={0:{rotateZ:-45+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{rotateZ:0+t.cur.rotateZ,opacity:1*t.dom.style.opacity}},o="left bottom";else if("rotateInDownRight"===a)n={0:{rotateZ:45+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{rotateZ:0+t.cur.rotateZ,opacity:1*t.dom.style.opacity}},o="right bottom";else if("rotateInUpLeft"===a)n={0:{rotateZ:45+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{rotateZ:+t.cur.rotateZ,opacity:1*t.dom.style.opacity}},o="left bottom";else if("rotateInUpRight"===a)n={0:{rotateZ:-90+t.cur.rotateZ,opacity:0*t.dom.style.opacity},1:{rotateZ:0+t.cur.rotateZ,opacity:1*t.dom.style.opacity}},o="right bottom";else if("rotateOut"===a)n={0:{opacity:1*t.dom.style.opacity},1:{rotateZ:200+t.cur.rotateZ,opacity:0*t.dom.style.opacity}},o="center";else if("rotateOutDownLeft"===a)n={0:{opacity:1*t.dom.style.opacity},1:{rotateZ:45+t.cur.rotateZ,opacity:0*t.dom.style.opacity}},o="left bottom";else if("rotateOutDownRight"===a)n={0:{opacity:1*t.dom.style.opacity},1:{rotateZ:-45+t.cur.rotateZ,opacity:0*t.dom.style.opacity}},o="right bottom";else if("rotateOutUpLeft"===a)n={0:{opacity:1*t.dom.style.opacity},1:{rotateZ:-45+t.cur.rotateZ,opacity:0*t.dom.style.opacity}},o="left bottom";else if("rotateOutUpRight"===a)n={0:{opacity:1*t.dom.style.opacity},1:{rotateZ:90+t.cur.rotateZ,opacity:0*t.dom.style.opacity}},o="right bottom";else{if("hinge"!==a)throw Error("the name of animation is not exists");n={0:{opacity:1*t.dom.style.opacity},.2:{rotateZ:80+t.cur.rotateZ},.4:{rotateZ:60+t.cur.rotateZ,opacity:1*t.dom.style.opacity},.6:{rotateZ:80+t.cur.rotateZ},.8:{rotateZ:60+t.cur.rotateZ,opacity:1*t.dom.style.opacity},1:{translateY:700+t.cur.translateY,opacity:0*t.dom.style.opacity}},o="top left",r=["easeInOut","easeInOut","easeInOut","easeInOut","easeInOut","easeInOut"]}return[n,r,o,s]}};e.AnimationUtil=i}(t,e,e.base),function(t,e,i){var a,n=i.Class.extend({_init:function(){return void 0!==a?a=new this:(this.targetObjects=[],this)},addTarget:function(t){this.targetObjects.push(t),t.map=new e.base.WeakMap},getObject:function(t){if(t instanceof e.AnimationObject)return t;for(var i=0,a=this.targetObjects.length;a>i;i++)if(t instanceof this.targetObjects[i].$type){var n=this.targetObjects[i].map.get(t);return void 0===n&&(n=new e[this.targetObjects[i].$namespace](t),this.targetObjects[i].map.set(t,n)),n}throw"CannotCreateObject"},"static":{getInstance:function(){return void 0===a&&(a=new n),a},plugin:function(t){function i(){e.AnimationObject.call(this),t.$constructor.apply(this,arguments)}var a=/^\$(?:namespace|constructor|type)$/;if(t.$constructor){i.prototype=new e.AnimationObject,i.prototype.constructor=i;for(var n in t)a.test(n)||(i.prototype[n]="function"==typeof t[n]&&t[n]);return e[t.$namespace]=i,this.getInstance().addTarget(t),i}}}});e.ObjectManager=n}(t,e,e.base),function(t){"use strict";(function(t,e,i){var a=e.base.Class.extend({_init:function(){this.from=new e.Transform,this.cur=i.copy(this.from),this.updateSeek=!1,this.updateSeekProperty=[]},getFrom:function(t){var e={},t=t.animation;for(var i in t)e[i]=this.from[i],this.from[i]=t[i];return e},setFrom:function(t){this.from.set(t)},translate:function(){},rotate:function(){}});e.AnimationObject=a})(t,e,e.base)}(t),function(t,e,i){"use strict";var a=e.CssAnimationUtil.getInstance(),n=e.CssStringCreator.getInstance();e.ObjectManager.plugin({$namespace:"DomObject",$type:t.HTMLElement,$constructor:function(t){this.dom=t,this.unit={},this._perspective=!1},render:function(t){var e,i,a=t.updateProperty;for(e=0;i=a[e];e++)t.targetStyle[i]=n[i](this,t.unit)},objectRender:function(t){var e=!1;for(var i in t)this.isTransform(i)||void 0===this.dom.style[i]?e||(this.dom.style.WebkitTransform=n.WebkitTransform(t),e=!0):this.dom.style[i]=n[i](t,unit)},createTweenInfo:function(t,e,i){var a={fromTo:{},animationFromTo:t,cur:this.cur,option:e,name:[],unit:{},target:this,targetStyle:this.dom.style,updateProperty:[]};return i&&this.setAnimationFromTo(a),a},setAnimationFromTo:function(t){var e,n=!1,r=t.animationFromTo;for(e in r)this.isTransform(e)?(a.WebkitTransform(e,t),n||(t.updateProperty.push("WebkitTransform"),n=!0)):"perspective"===e?(this._perspective=i.isNumber(r[e])?r[e]:i.isNumber(r[e][1])?r[e][1]:0,this.cur.perspective=this._perspective):a[e]&&(a[e](t),t.updateProperty.push(e))},isTransform:function(t){return void 0!==t&&null!==t?"translateX"===t||"translateY"===t||"translateZ"===t||"rotateX"===t||"rotateY"===t||"rotateZ"===t||"scaleX"===t||"scaleY"===t||"skewX"===t||"skewY"===t?!0:!1:void 0},perspective:function(t){void 0!==t&&null!==t&&e.base.isNumber(t)&&(this._perspective=t,this.cur.perspective=t)},set:function(t){if(void 0!==t&&null!==t){for(var e in t)this.isTransform(e)?(this.from[e]=t[e],this.cur[e]=t[e]):"perspective"===e?this.perspective(t[e]):this.dom.style[e]=t[e];this.objectRender(i.deepCopy(this.from))}}})}(t,e,e.base),function(t,e,i){"use strict";function a(t){var i,a;for(this.target=[],this.len=t.length,i=0;this.len>i;i++)this.target[i]=(a=n.getObject(t[i]).simpleAnimation)?a:new e.SimpleAnimation(t[i])}var n=e.ObjectManager.getInstance(),r={tween:function(t,i,a){var n;return this.simpleAnimation||(this.simpleAnimation=this.length?new e.SimpleAnimationGroup(this):new e.SimpleAnimation(this)),n=e.AnimationUtil.optionAnalyzer(i,a),this.simpleAnimation.add(t,n),this.simpleAnimation.play(),this},stop:function(){this.simpleAnimation||this.simpleAnimation||(this.simpleAnimation=this.length?new e.SimpleAnimationGroup(this):new e.SimpleAnimation(this)),this.simpleAnimation.stop()},transform:function(t){this.simpleAnimation||(this.simpleAnimation=this.length?new e.SimpleAnimationGroup(this):new e.SimpleAnimation(this)),this.simpleAnimation.target.set(t)}},o=function(t){this.tweenAnimator=new e.TweenAnimator,this.target=n.getObject(t),this.target.simpleAnimation=this,this.target.render&&this.tweenAnimator.setRender(this.target.render),this.target.cur&&this.tweenAnimator.setUpdateTarget(this.target.cur)};o.prototype.add=function(t,a,n){var r,o,s,c,l=n||this.tweenAnimator,u=this;return"string"==typeof t?(r=e.AnimationUtil.effectAnalyzer(this.target,t),e.AnimationUtil.createKeyFrame(r[0],a,function(t,e,i){void 0!==r[1]&&(e.ease=r[1][i]),o=u.target.createTweenInfo(t,e,!0),l.add(o),void 0!==r[2]&&(0===i?o.startCallback.on(function(){u.target.dom.style.webkitTransformOrigin=r[2]}):i===r.length&&o.completeCallback.on(function(){u.target.dom.style.webkitTransformOrigin=""})),void 0!==r[3]&&o.completeCallback.on(function(){u.target.dom.style.visibility=r[3]})}),void 0):(t.effect&&(void 0===this.parTweensGroup?(this.parTweensGroup=[],c=new e.TweenAnimator,this.parTweensGroup.push(c)):c=this.parTweensGroup[0],this.target.render&&c.setRender(this.target.render),this.target.cur&&c.setUpdateTarget(this.target.cur),this.add(t.effect,i.deepCopy(a),c)),"running"===l.getState()?(o=u.target.createTweenInfo(t,a,!1),(s=l.getLastTweenInfo())&&s.completeCallback.on(function(){u.target.setAnimationFromTo(o)})):o=this.target.createTweenInfo(t,a,!0),l.add(o),void 0)},o.prototype.play=function(){var t,e;if(this.tweenAnimator.play(),this.parTweensGroup)for(t=0,e=this.parTweensGroup.length;e>t;t++)this.parTweensGroup[t].play()},o.prototype.stop=function(){var t,e;if(this.tweenAnimator.stop(),this.parTweensGroup)for(t=0,e=this.parTweensGroup.length;e>t;t++)this.parTweensGroup[t].stop()},a.prototype.add=function(t,i){var a=0,n=this;e.AnimationUtil.checkStagger(this.target,i,function(e,r){i.onComplete&&(r.onComplete=function(){a++,a===n.len&&e.tweenAnimator.getCurrentTweenInfo().completeCallback.on(i.onComplete)}),e.add(t,r)})},a.prototype.play=function(){var t;for(t=0;this.len>t;t++)this.target[t].play()},a.prototype.stop=function(){var t;for(t=0;this.len>t;t++)this.target[t].stop()},e.SimpleAnimation=o,e.SimpleAnimationGroup=a,e.SimpleAnimationMixinObject=r}(t,e,e.base),function(t,e){"use strict";function i(t){var e,i,a=["tween","stop","transform","simpleAnimation"];for(e=0,i=a.length;i>e;e++)if(t.hasOwnProperty(a[e]))return a[e];return!1}function a(t){var e="Function or Object can apply Mixin";e+=void 0!==t?': "'+t+'" is overrided.':".",console.warn(e)}var n=e.SimpleAnimationMixinObject,r=function(t){var e;if(void 0!==t.prototype){(e=i(t.prototype))&&a(e);for(var r in n)t.prototype[r]=n[r]}else if(t instanceof Object){(e=i(t))&&a(e);for(var r in n)n.hasOwnProperty(r)&&(t[r]=n[r])}else a();return t};e.SimpleMixin=r}(t,e),function(t,e){"use strict";var i=e.ObjectManager.getInstance();e.SimpleMixin(e.DomObject),e.target=function(a){if("string"==typeof a){var n,r=a.slice(0,1),o=a.slice(1);"."===r?(n=document.getElementsByClassName(o),n.tween||e.SimpleMixin(n,function(){return n})):"#"===r&&(n=document.getElementById(o),n=i.getObject(n))}else a instanceof t.HTMLElement&&(n=i.getObject(a));return n}}(t,e)})(window); \ No newline at end of file diff --git a/d2d_app/client/lib/tau/mobile/js/jquery.js b/d2d_app/client/lib/tau/mobile/js/jquery.js new file mode 100644 index 00000000..9f7b3d38 --- /dev/null +++ b/d2d_app/client/lib/tau/mobile/js/jquery.js @@ -0,0 +1,9190 @@ +/*! + * jQuery JavaScript Library v2.1.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-05-01T17:11Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper window is present, + // execute the factory and get jQuery + // For environments that do not inherently posses a window with a document + // (such as Node.js), expose a jQuery-making factory as module.exports + // This accentuates the need for the creation of a real window + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var arr = []; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + version = "2.1.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + }, + + isPlainObject: function( obj ) { + // Not plain objects: + // - Any object or value whose internal [[Class]] property is not "[object Object]" + // - DOM nodes + // - window + if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.constructor && + !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + + // If the function hasn't returned already, we're confident that + // |obj| is a plain object, created by {} or constructed with new Object + return true; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + // Support: Android < 4.0, iOS < 6 (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + var script, + indirect = eval; + + code = jQuery.trim( code ); + + if ( code ) { + // If the code includes a valid, prologue position + // strict mode pragma, execute code by injecting a + // script tag into the document. + if ( code.indexOf("use strict") === 1 ) { + script = document.createElement("script"); + script.text = code; + document.head.appendChild( script ).parentNode.removeChild( script ); + } else { + // Otherwise, avoid the DOM node creation, insertion + // and removal by using an indirect global eval + indirect( code ); + } + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v1.10.19 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-04-18 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== strundefined && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, + doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", function() { + setDocument(); + }, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", function() { + setDocument(); + }); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowclip^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + len = this.length, + ret = [], + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; + }, + + sibling: function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter(function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return elem.contentDocument || jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.unique( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * The ready event handler and self cleanup method + */ +function completed() { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + jQuery.ready(); +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + } else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + } + } + return readyList.promise( obj ); +}; + +// Kick off the DOM ready check even if the user does not +jQuery.ready.promise(); + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + len ? fn( elems[0], key ) : emptyGet; +}; + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( owner ) { + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + /* jshint -W018 */ + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + +function Data() { + // Support: Android < 4, + // Old WebKit does not have Object.preventExtensions/freeze method, + // return new empty object instead with no [[set]] accessor + Object.defineProperty( this.cache = {}, 0, { + get: function() { + return {}; + } + }); + + this.expando = jQuery.expando + Math.random(); +} + +Data.uid = 1; +Data.accepts = jQuery.acceptData; + +Data.prototype = { + key: function( owner ) { + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return the key for a frozen object. + if ( !Data.accepts( owner ) ) { + return 0; + } + + var descriptor = {}, + // Check if the owner object already has a cache key + unlock = owner[ this.expando ]; + + // If not, create one + if ( !unlock ) { + unlock = Data.uid++; + + // Secure it in a non-enumerable, non-writable property + try { + descriptor[ this.expando ] = { value: unlock }; + Object.defineProperties( owner, descriptor ); + + // Support: Android < 4 + // Fallback to a less secure definition + } catch ( e ) { + descriptor[ this.expando ] = unlock; + jQuery.extend( owner, descriptor ); + } + } + + // Ensure the cache object + if ( !this.cache[ unlock ] ) { + this.cache[ unlock ] = {}; + } + + return unlock; + }, + set: function( owner, data, value ) { + var prop, + // There may be an unlock assigned to this node, + // if there is no entry for this "owner", create one inline + // and set the unlock as though an owner entry had always existed + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + // Handle: [ owner, key, value ] args + if ( typeof data === "string" ) { + cache[ data ] = value; + + // Handle: [ owner, { properties } ] args + } else { + // Fresh assignments by object are shallow copied + if ( jQuery.isEmptyObject( cache ) ) { + jQuery.extend( this.cache[ unlock ], data ); + // Otherwise, copy the properties one-by-one to the cache object + } else { + for ( prop in data ) { + cache[ prop ] = data[ prop ]; + } + } + } + return cache; + }, + get: function( owner, key ) { + // Either a valid cache is found, or will be created. + // New caches will be created and the unlock returned, + // allowing direct access to the newly created + // empty data object. A valid owner object must be provided. + var cache = this.cache[ this.key( owner ) ]; + + return key === undefined ? + cache : cache[ key ]; + }, + access: function( owner, key, value ) { + var stored; + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ((key && typeof key === "string") && value === undefined) ) { + + stored = this.get( owner, key ); + + return stored !== undefined ? + stored : this.get( owner, jQuery.camelCase(key) ); + } + + // [*]When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, name, camel, + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + if ( key === undefined ) { + this.cache[ unlock ] = {}; + + } else { + // Support array or space separated string of keys + if ( jQuery.isArray( key ) ) { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = key.concat( key.map( jQuery.camelCase ) ); + } else { + camel = jQuery.camelCase( key ); + // Try the string as a key before any manipulation + if ( key in cache ) { + name = [ key, camel ]; + } else { + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + name = camel; + name = name in cache ? + [ name ] : ( name.match( rnotwhite ) || [] ); + } + } + + i = name.length; + while ( i-- ) { + delete cache[ name[ i ] ]; + } + } + }, + hasData: function( owner ) { + return !jQuery.isEmptyObject( + this.cache[ owner[ this.expando ] ] || {} + ); + }, + discard: function( owner ) { + if ( owner[ this.expando ] ) { + delete this.cache[ owner[ this.expando ] ]; + } + } +}; +var data_priv = new Data(); + +var data_user = new Data(); + + + +/* + Implementation Summary + + 1. Enforce API surface and semantic compatibility with 1.9.x branch + 2. Improve the module's maintainability by reducing the storage + paths to a single mechanism. + 3. Use the same single mechanism to support "private" and "user" data. + 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) + 5. Avoid exposing implementation details on user objects (eg. expando properties) + 6. Provide a clear path for implementation upgrade to WeakMap in 2014 +*/ +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + data_user.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend({ + hasData: function( elem ) { + return data_user.hasData( elem ) || data_priv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return data_user.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + data_user.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to data_priv methods, these can be deprecated. + _data: function( elem, name, data ) { + return data_priv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + data_priv.remove( elem, name ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = data_user.get( elem ); + + if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + data_priv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + data_user.set( this, key ); + }); + } + + return access( this, function( value ) { + var data, + camelKey = jQuery.camelCase( key ); + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + // Attempt to get data from the cache + // with the key as-is + data = data_user.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to get data from the cache + // with the key camelized + data = data_user.get( elem, camelKey ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, camelKey, undefined ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each(function() { + // First, attempt to store a copy or reference of any + // data that might've been store with a camelCased key. + var data = data_user.get( this, camelKey ); + + // For HTML5 data-* attribute interop, we have to + // store property names with dashes in a camelCase form. + // This might not apply to all properties...* + data_user.set( this, camelKey, value ); + + // *... In the case of properties that might _actually_ + // have dashes, we need to also store a copy of that + // unchanged property. + if ( key.indexOf("-") !== -1 && data !== undefined ) { + data_user.set( this, key, value ); + } + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + data_user.remove( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = data_priv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = data_priv.access( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return data_priv.get( elem, key ) || data_priv.access( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + data_priv.remove( elem, [ type + "queue", key ] ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = data_priv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // #11217 - WebKit loses check when the name is after the checked attribute + // Support: Windows Web Apps (WWA) + // `name` and `type` need .setAttribute for WWA + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE9-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +})(); +var strundefined = typeof undefined; + + + +support.focusinBubbles = "onfocusin" in window; + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.hasData( elem ) && data_priv.get( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + data_priv.remove( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.disabled !== true || event.type !== "click" ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: Cordova 2.5 (WebKit) (#13255) + // All events should have a target; Cordova deviceready doesn't + if ( !event.target ) { + event.target = document; + } + + // Support: Safari 6.0+, Chrome < 28 + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } +}; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && e.preventDefault ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && e.stopPropagation ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +// Support: Chrome 15+ +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// Create "bubbling" focus and blur events +// Support: Firefox, Chrome, Safari +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = data_priv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = data_priv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + data_priv.remove( doc, fix ); + + } else { + data_priv.access( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +var + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rhtml = /<|&#?\w+;/, + rnoInnerhtml = /<(?:script|style|link)/i, + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /^$|\/(?:java|ecma)script/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + + // Support: IE 9 + option: [ 1, "" ], + + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] + }; + +// Support: IE 9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: 1.x compatibility +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute("type"); + } + + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + data_priv.set( + elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) + ); + } +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( data_priv.hasData( src ) ) { + pdataOld = data_priv.access( src ); + pdataCur = data_priv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( data_user.hasData( src ) ) { + udataOld = data_user.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + data_user.set( dest, udataCur ); + } +} + +function getAll( context, tag ) { + var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : + context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : + []; + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} + +// Support: IE >= 9 +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Support: IE >= 9 + // Fix Cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + // Support: QtWebKit + // jQuery.merge because push.apply(_, arraylike) throws + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: QtWebKit + // jQuery.merge because push.apply(_, arraylike) throws + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Fixes #12346 + // Support: Webkit, IE + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; + }, + + cleanData: function( elems ) { + var data, elem, type, key, + special = jQuery.event.special, + i = 0; + + for ( ; (elem = elems[ i ]) !== undefined; i++ ) { + if ( jQuery.acceptData( elem ) ) { + key = elem[ data_priv.expando ]; + + if ( key && (data = data_priv.cache[ key ]) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + if ( data_priv.cache[ key ] ) { + // Discard any remaining `private` data + delete data_priv.cache[ key ]; + } + } + } + // Discard any remaining `user` data + delete data_user.cache[ elem[ data_user.expando ] ]; + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each(function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + }); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + // Support: QtWebKit + // jQuery.merge because push.apply(_, arraylike) throws + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); + } + } + } + } + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: QtWebKit + // .get() because push.apply(_, arraylike) throws + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( "