New file |
| | |
| | | AngularJS-todoapp |
| | | ================= |
| | | |
| | | Pure client-side todoapp, implemented in AngularJS. There is no REST interaction here, the objects are stored in memory. |
| | | |
| | | Integrates: |
| | | - angularjs |
| | | - bootstrap |
| | | - angular-ui-router |
| | | - angular-xeditable |
| | | - angular-strap |
| | | |
| | | |
| | | Running in Firefox |
| | | ------ |
| | | Will run directly in Firefox; just open up index.html |
| | | |
| | | Running in Chrome |
| | | ------ |
| | | Chrome does not support XMLHttpRequest calls to file://, so the app must be hosted. |
| | | |
| | | If you have Python installed, use: |
| | | |
| | | python -m SimpleHTTPServer 8080 |
| | | |
| | | Then navigate to [http://localhost:8080](http://localhost:8080) |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <module type="WEB_MODULE" version="4"> |
| | | <component name="NewModuleRootManager" inherit-compiler-output="true"> |
| | | <exclude-output /> |
| | | <content url="file://$MODULE_DIR$" /> |
| | | <orderEntry type="inheritedJdk" /> |
| | | <orderEntry type="sourceFolder" forTests="false" /> |
| | | </component> |
| | | </module> |
| | | |
New file |
| | |
| | | a.form-control-static.editable-click { |
| | | display: block; |
| | | border-bottom: none; |
| | | } |
| | | .form-control-static pre { |
| | | background-color: transparent; |
| | | } |
| | | |
| | | .btn .label { |
| | | padding-left: 5px; |
| | | } |
New file |
| | |
| | | <?xml version="1.0" standalone="no"?> |
| | | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > |
| | | <svg xmlns="http://www.w3.org/2000/svg"> |
| | | <metadata></metadata> |
| | | <defs> |
| | | <font id="glyphicons_halflingsregular" horiz-adv-x="1200" > |
| | | <font-face units-per-em="1200" ascent="960" descent="-240" /> |
| | | <missing-glyph horiz-adv-x="500" /> |
| | | <glyph /> |
| | | <glyph /> |
| | | <glyph unicode="
" /> |
| | | <glyph unicode=" " /> |
| | | <glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" /> |
| | | <glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" /> |
| | | <glyph unicode=" " /> |
| | | <glyph unicode=" " horiz-adv-x="652" /> |
| | | <glyph unicode=" " horiz-adv-x="1304" /> |
| | | <glyph unicode=" " horiz-adv-x="652" /> |
| | | <glyph unicode=" " horiz-adv-x="1304" /> |
| | | <glyph unicode=" " horiz-adv-x="434" /> |
| | | <glyph unicode=" " horiz-adv-x="326" /> |
| | | <glyph unicode=" " horiz-adv-x="217" /> |
| | | <glyph unicode=" " horiz-adv-x="217" /> |
| | | <glyph unicode=" " horiz-adv-x="163" /> |
| | | <glyph unicode=" " horiz-adv-x="260" /> |
| | | <glyph unicode=" " horiz-adv-x="72" /> |
| | | <glyph unicode=" " horiz-adv-x="260" /> |
| | | <glyph unicode=" " horiz-adv-x="326" /> |
| | | <glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" /> |
| | | <glyph unicode="−" d="M200 400h900v300h-900v-300z" /> |
| | | <glyph unicode="◼" horiz-adv-x="500" d="M0 0z" /> |
| | | <glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" /> |
| | | <glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" /> |
| | | <glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" /> |
| | | <glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" /> |
| | | <glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" /> |
| | | <glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" /> |
| | | <glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" /> |
| | | <glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" /> |
| | | <glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" /> |
| | | <glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" /> |
| | | <glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" /> |
| | | <glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" /> |
| | | <glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" /> |
| | | <glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" /> |
| | | <glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" /> |
| | | <glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" /> |
| | | <glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" /> |
| | | <glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" /> |
| | | <glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" /> |
| | | <glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" /> |
| | | <glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" /> |
| | | <glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" /> |
| | | <glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" /> |
| | | <glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" /> |
| | | <glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" /> |
| | | <glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" /> |
| | | <glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" /> |
| | | <glyph unicode="" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" /> |
| | | <glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" /> |
| | | <glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" /> |
| | | <glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" /> |
| | | <glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" /> |
| | | <glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" /> |
| | | <glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" /> |
| | | <glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" /> |
| | | <glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" /> |
| | | <glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" /> |
| | | <glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" /> |
| | | <glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" /> |
| | | <glyph unicode="" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" /> |
| | | <glyph unicode="" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" /> |
| | | <glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" /> |
| | | <glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" /> |
| | | <glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" /> |
| | | <glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" /> |
| | | <glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" /> |
| | | <glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" /> |
| | | <glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" /> |
| | | <glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " /> |
| | | <glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" /> |
| | | <glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> |
| | | <glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> |
| | | <glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" /> |
| | | <glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> |
| | | <glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" /> |
| | | <glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" /> |
| | | <glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" /> |
| | | <glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" /> |
| | | <glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " /> |
| | | <glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" /> |
| | | <glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" /> |
| | | <glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" /> |
| | | <glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" /> |
| | | <glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" /> |
| | | <glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" /> |
| | | <glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" /> |
| | | <glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> |
| | | <glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> |
| | | <glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" /> |
| | | <glyph unicode="" d="M200 0l900 550l-900 550v-1100z" /> |
| | | <glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> |
| | | <glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> |
| | | <glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" /> |
| | | <glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" /> |
| | | <glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" /> |
| | | <glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" /> |
| | | <glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" /> |
| | | <glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" /> |
| | | <glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" /> |
| | | <glyph unicode="" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" /> |
| | | <glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" /> |
| | | <glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" /> |
| | | <glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" /> |
| | | <glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" /> |
| | | <glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" /> |
| | | <glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" /> |
| | | <glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" /> |
| | | <glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" /> |
| | | <glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" /> |
| | | <glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" /> |
| | | <glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" /> |
| | | <glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" /> |
| | | <glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" /> |
| | | <glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" /> |
| | | <glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" /> |
| | | <glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" /> |
| | | <glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" /> |
| | | <glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" /> |
| | | <glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" /> |
| | | <glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" /> |
| | | <glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" /> |
| | | <glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" /> |
| | | <glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" /> |
| | | <glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" /> |
| | | <glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" /> |
| | | <glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" /> |
| | | <glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" /> |
| | | <glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" /> |
| | | <glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" /> |
| | | <glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" /> |
| | | <glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" /> |
| | | <glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" /> |
| | | <glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" /> |
| | | <glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" /> |
| | | <glyph unicode="" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" /> |
| | | <glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" /> |
| | | <glyph unicode="" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" /> |
| | | <glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" /> |
| | | <glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" /> |
| | | <glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" /> |
| | | <glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" /> |
| | | <glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" /> |
| | | <glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" /> |
| | | <glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" /> |
| | | <glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" /> |
| | | <glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" /> |
| | | <glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" /> |
| | | <glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" /> |
| | | <glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" /> |
| | | <glyph unicode="" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" /> |
| | | <glyph unicode="" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" /> |
| | | <glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" /> |
| | | <glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" /> |
| | | <glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" /> |
| | | <glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" /> |
| | | <glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" /> |
| | | <glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" /> |
| | | <glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" /> |
| | | <glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" /> |
| | | <glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" /> |
| | | <glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" /> |
| | | <glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" /> |
| | | <glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" /> |
| | | <glyph unicode="" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" /> |
| | | <glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " /> |
| | | <glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" /> |
| | | <glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" /> |
| | | <glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" /> |
| | | <glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" /> |
| | | <glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" /> |
| | | <glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" /> |
| | | <glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" /> |
| | | <glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" /> |
| | | <glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" /> |
| | | <glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" /> |
| | | <glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" /> |
| | | <glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" /> |
| | | <glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" /> |
| | | <glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" /> |
| | | <glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" /> |
| | | <glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" /> |
| | | <glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" /> |
| | | <glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" /> |
| | | <glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> |
| | | <glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" /> |
| | | <glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" /> |
| | | <glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" /> |
| | | <glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" /> |
| | | <glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" /> |
| | | <glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" /> |
| | | <glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" /> |
| | | </font> |
| | | </defs></svg> |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-scale { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-scale.ng-enter, |
| | | .am-fade-and-scale.am-fade-and-scale-add, |
| | | .am-fade-and-scale.ng-hide-remove, |
| | | .am-fade-and-scale.ng-move { |
| | | -webkit-animation-name: fadeAndScaleIn; |
| | | animation-name: fadeAndScaleIn; |
| | | } |
| | | .am-fade-and-scale.ng-leave, |
| | | .am-fade-and-scale.am-fade-and-scale-remove, |
| | | .am-fade-and-scale.ng-hide { |
| | | -webkit-animation-name: fadeAndScaleOut; |
| | | animation-name: fadeAndScaleOut; |
| | | } |
| | | .am-fade-and-scale.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndScaleIn; |
| | | animation-name: fadeAndScaleIn; |
| | | } |
| | | .am-fade-and-scale.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-scale.ng-leave { |
| | | -webkit-animation-name: fadeAndScaleOut; |
| | | animation-name: fadeAndScaleOut; |
| | | } |
| | | @-webkit-keyframes fadeAndScaleIn { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndScaleIn { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndScaleOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | } |
| | | @keyframes fadeAndScaleOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | } |
| | | |
| | | .am-fade-and-slide-top { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-top.am-fade-and-slide-top-add, |
| | | .am-fade-and-slide-top.ng-hide-remove, |
| | | .am-fade-and-slide-top.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromTop; |
| | | animation-name: fadeAndSlideFromTop; |
| | | } |
| | | .am-fade-and-slide-top.am-fade-and-slide-top-remove, |
| | | .am-fade-and-slide-top.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToTop; |
| | | animation-name: fadeAndSlideToTop; |
| | | } |
| | | .am-fade-and-slide-top.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromTop; |
| | | animation-name: fadeAndSlideFromTop; |
| | | } |
| | | .am-fade-and-slide-top.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-top.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToTop; |
| | | animation-name: fadeAndSlideToTop; |
| | | } |
| | | .am-fade-and-slide-right { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-right.am-fade-and-slide-right-add, |
| | | .am-fade-and-slide-right.ng-hide-remove, |
| | | .am-fade-and-slide-right.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromRight; |
| | | animation-name: fadeAndSlideFromRight; |
| | | } |
| | | .am-fade-and-slide-right.am-fade-and-slide-right-remove, |
| | | .am-fade-and-slide-right.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToRight; |
| | | animation-name: fadeAndSlideToRight; |
| | | } |
| | | .am-fade-and-slide-right.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromRight; |
| | | animation-name: fadeAndSlideFromRight; |
| | | } |
| | | .am-fade-and-slide-right.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-right.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToRight; |
| | | animation-name: fadeAndSlideToRight; |
| | | } |
| | | .am-fade-and-slide-bottom { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-bottom.am-fade-and-slide-bottom-add, |
| | | .am-fade-and-slide-bottom.ng-hide-remove, |
| | | .am-fade-and-slide-bottom.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromBottom; |
| | | animation-name: fadeAndSlideFromBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.am-fade-and-slide-bottom-remove, |
| | | .am-fade-and-slide-bottom.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToBottom; |
| | | animation-name: fadeAndSlideToBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromBottom; |
| | | animation-name: fadeAndSlideFromBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToBottom; |
| | | animation-name: fadeAndSlideToBottom; |
| | | } |
| | | .am-fade-and-slide-left { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-left.am-fade-and-slide-left-add, |
| | | .am-fade-and-slide-left.ng-hide-remove, |
| | | .am-fade-and-slide-left.ng-move { |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | -webkit-animation-name: fadeAndSlideFromLeft; |
| | | animation-name: fadeAndSlideFromLeft; |
| | | } |
| | | .am-fade-and-slide-left.am-fade-and-slide-left-remove, |
| | | .am-fade-and-slide-left.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToLeft; |
| | | animation-name: fadeAndSlideToLeft; |
| | | } |
| | | .am-fade-and-slide-left.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromLeft; |
| | | animation-name: fadeAndSlideFromLeft; |
| | | } |
| | | .am-fade-and-slide-left.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-left.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToLeft; |
| | | animation-name: fadeAndSlideToLeft; |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromTop { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromTop { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToTop { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToTop { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromRight { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromRight { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToRight { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToRight { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromBottom { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromBottom { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToBottom { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToBottom { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromLeft { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromLeft { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToLeft { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToLeft { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | } |
| | | |
| | | .am-fade { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: linear; |
| | | animation-timing-function: linear; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | opacity: 1; |
| | | } |
| | | .am-fade.am-fade-add, |
| | | .am-fade.ng-hide-remove, |
| | | .am-fade.ng-move { |
| | | -webkit-animation-name: fadeIn; |
| | | animation-name: fadeIn; |
| | | } |
| | | .am-fade.am-fade-remove, |
| | | .am-fade.ng-hide { |
| | | -webkit-animation-name: fadeOut; |
| | | animation-name: fadeOut; |
| | | } |
| | | .am-fade.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeIn; |
| | | animation-name: fadeIn; |
| | | } |
| | | .am-fade.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade.ng-leave { |
| | | -webkit-animation-name: fadeOut; |
| | | animation-name: fadeOut; |
| | | } |
| | | @-webkit-keyframes fadeIn { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeIn { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | } |
| | | } |
| | | @keyframes fadeOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | } |
| | | } |
| | | .modal-backdrop.am-fade, |
| | | .aside-backdrop.am-fade { |
| | | background: rgba(0, 0, 0, 0.5); |
| | | -webkit-animation-duration: 0.15s; |
| | | animation-duration: 0.15s; |
| | | } |
| | | |
| | | .am-flip-x { |
| | | -webkit-animation-duration: 0.4s; |
| | | animation-duration: 0.4s; |
| | | -webkit-animation-timing-function: ease; |
| | | animation-timing-function: ease; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-flip-x.am-flip-x-add, |
| | | .am-flip-x.ng-hide-remove, |
| | | .am-flip-x.ng-move { |
| | | -webkit-animation-name: flipInXBounce; |
| | | animation-name: flipInXBounce; |
| | | } |
| | | .am-flip-x.am-flip-x-remove, |
| | | .am-flip-x.ng-hide { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: flipInXBounce; |
| | | animation-name: flipInXBounce; |
| | | } |
| | | .am-flip-x.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-flip-x.ng-leave { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x-linear { |
| | | -webkit-animation-duration: 0.4s; |
| | | animation-duration: 0.4s; |
| | | -webkit-animation-timing-function: ease; |
| | | animation-timing-function: ease; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-flip-x-linear.am-flip-x-add, |
| | | .am-flip-x-linear.ng-hide-remove, |
| | | .am-flip-x-linear.ng-move { |
| | | -webkit-animation-name: flipInX; |
| | | animation-name: flipInX; |
| | | } |
| | | .am-flip-x-linear.am-flip-x-remove, |
| | | .am-flip-x-linear.ng-hide { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x-linear.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: flipInX; |
| | | animation-name: flipInX; |
| | | } |
| | | .am-flip-x-linear.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-flip-x-linear.ng-leave { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | @-webkit-keyframes flipInX { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @keyframes flipInX { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @-webkit-keyframes flipInXBounce { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | 40% { |
| | | -webkit-transform: perspective(400px) rotateX(-10deg); |
| | | transform: perspective(400px) rotateX(-10deg); |
| | | } |
| | | 70% { |
| | | -webkit-transform: perspective(400px) rotateX(10deg); |
| | | transform: perspective(400px) rotateX(10deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @keyframes flipInXBounce { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | 40% { |
| | | -webkit-transform: perspective(400px) rotateX(-10deg); |
| | | transform: perspective(400px) rotateX(-10deg); |
| | | } |
| | | 70% { |
| | | -webkit-transform: perspective(400px) rotateX(10deg); |
| | | transform: perspective(400px) rotateX(10deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @-webkit-keyframes flipOutX { |
| | | from { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | } |
| | | @keyframes flipOutX { |
| | | from { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | } |
| | | |
| | | .am-slide-top { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-top.am-fade-and-slide-top-add, |
| | | .am-slide-top.ng-hide-remove, |
| | | .am-slide-top.ng-move { |
| | | -webkit-animation-name: slideFromTop; |
| | | animation-name: slideFromTop; |
| | | } |
| | | .am-slide-top.am-fade-and-slide-top-remove, |
| | | .am-slide-top.ng-hide { |
| | | -webkit-animation-name: slideToTop; |
| | | animation-name: slideToTop; |
| | | } |
| | | .am-slide-top.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromTop; |
| | | animation-name: slideFromTop; |
| | | } |
| | | .am-slide-top.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-top.ng-leave { |
| | | -webkit-animation-name: slideToTop; |
| | | animation-name: slideToTop; |
| | | } |
| | | .am-slide-right { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-right.am-fade-and-slide-right-add, |
| | | .am-slide-right.ng-hide-remove, |
| | | .am-slide-right.ng-move { |
| | | -webkit-animation-name: slideFromRight; |
| | | animation-name: slideFromRight; |
| | | } |
| | | .am-slide-right.am-fade-and-slide-right-remove, |
| | | .am-slide-right.ng-hide { |
| | | -webkit-animation-name: slideToRight; |
| | | animation-name: slideToRight; |
| | | } |
| | | .am-slide-right.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromRight; |
| | | animation-name: slideFromRight; |
| | | } |
| | | .am-slide-right.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-right.ng-leave { |
| | | -webkit-animation-name: slideToRight; |
| | | animation-name: slideToRight; |
| | | } |
| | | .am-slide-bottom { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-bottom.am-fade-and-slide-bottom-add, |
| | | .am-slide-bottom.ng-hide-remove, |
| | | .am-slide-bottom.ng-move { |
| | | -webkit-animation-name: slideFromBottom; |
| | | animation-name: slideFromBottom; |
| | | } |
| | | .am-slide-bottom.am-fade-and-slide-bottom-remove, |
| | | .am-slide-bottom.ng-hide { |
| | | -webkit-animation-name: slideToBottom; |
| | | animation-name: slideToBottom; |
| | | } |
| | | .am-slide-bottom.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromBottom; |
| | | animation-name: slideFromBottom; |
| | | } |
| | | .am-slide-bottom.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-bottom.ng-leave { |
| | | -webkit-animation-name: slideToBottom; |
| | | animation-name: slideToBottom; |
| | | } |
| | | .am-slide-left { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-left.am-fade-and-slide-left-add, |
| | | .am-slide-left.ng-hide-remove, |
| | | .am-slide-left.ng-move { |
| | | -webkit-animation-name: slideFromLeft; |
| | | animation-name: slideFromLeft; |
| | | } |
| | | .am-slide-left.am-fade-and-slide-left-remove, |
| | | .am-slide-left.ng-hide { |
| | | -webkit-animation-name: slideToLeft; |
| | | animation-name: slideToLeft; |
| | | } |
| | | .am-slide-left.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromLeft; |
| | | animation-name: slideFromLeft; |
| | | } |
| | | .am-slide-left.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-left.ng-leave { |
| | | -webkit-animation-name: slideToLeft; |
| | | animation-name: slideToLeft; |
| | | } |
| | | @-webkit-keyframes slideFromTop { |
| | | from { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @keyframes slideFromTop { |
| | | from { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToTop { |
| | | to { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @keyframes slideToTop { |
| | | to { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromRight { |
| | | from { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @keyframes slideFromRight { |
| | | from { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToRight { |
| | | to { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @keyframes slideToRight { |
| | | to { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromBottom { |
| | | from { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @keyframes slideFromBottom { |
| | | from { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToBottom { |
| | | to { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @keyframes slideToBottom { |
| | | to { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromLeft { |
| | | from { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @keyframes slideFromLeft { |
| | | from { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToLeft { |
| | | to { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @keyframes slideToLeft { |
| | | to { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-scale{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-scale.ng-enter,.am-fade-and-scale.am-fade-and-scale-add,.am-fade-and-scale.ng-hide-remove,.am-fade-and-scale.ng-move{-webkit-animation-name:fadeAndScaleIn;animation-name:fadeAndScaleIn}.am-fade-and-scale.ng-leave,.am-fade-and-scale.am-fade-and-scale-remove,.am-fade-and-scale.ng-hide{-webkit-animation-name:fadeAndScaleOut;animation-name:fadeAndScaleOut}.am-fade-and-scale.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndScaleIn;animation-name:fadeAndScaleIn}.am-fade-and-scale.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-scale.ng-leave{-webkit-animation-name:fadeAndScaleOut;animation-name:fadeAndScaleOut}@-webkit-keyframes fadeAndScaleIn{from{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}to{opacity:1}}@keyframes fadeAndScaleIn{from{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}to{opacity:1}}@-webkit-keyframes fadeAndScaleOut{from{opacity:1}to{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}}@keyframes fadeAndScaleOut{from{opacity:1}to{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}}.am-fade-and-slide-top{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-top.am-fade-and-slide-top-add,.am-fade-and-slide-top.ng-hide-remove,.am-fade-and-slide-top.ng-move{-webkit-animation-name:fadeAndSlideFromTop;animation-name:fadeAndSlideFromTop}.am-fade-and-slide-top.am-fade-and-slide-top-remove,.am-fade-and-slide-top.ng-hide{-webkit-animation-name:fadeAndSlideToTop;animation-name:fadeAndSlideToTop}.am-fade-and-slide-top.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromTop;animation-name:fadeAndSlideFromTop}.am-fade-and-slide-top.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-top.ng-leave{-webkit-animation-name:fadeAndSlideToTop;animation-name:fadeAndSlideToTop}.am-fade-and-slide-right{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-right.am-fade-and-slide-right-add,.am-fade-and-slide-right.ng-hide-remove,.am-fade-and-slide-right.ng-move{-webkit-animation-name:fadeAndSlideFromRight;animation-name:fadeAndSlideFromRight}.am-fade-and-slide-right.am-fade-and-slide-right-remove,.am-fade-and-slide-right.ng-hide{-webkit-animation-name:fadeAndSlideToRight;animation-name:fadeAndSlideToRight}.am-fade-and-slide-right.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromRight;animation-name:fadeAndSlideFromRight}.am-fade-and-slide-right.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-right.ng-leave{-webkit-animation-name:fadeAndSlideToRight;animation-name:fadeAndSlideToRight}.am-fade-and-slide-bottom{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-bottom.am-fade-and-slide-bottom-add,.am-fade-and-slide-bottom.ng-hide-remove,.am-fade-and-slide-bottom.ng-move{-webkit-animation-name:fadeAndSlideFromBottom;animation-name:fadeAndSlideFromBottom}.am-fade-and-slide-bottom.am-fade-and-slide-bottom-remove,.am-fade-and-slide-bottom.ng-hide{-webkit-animation-name:fadeAndSlideToBottom;animation-name:fadeAndSlideToBottom}.am-fade-and-slide-bottom.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromBottom;animation-name:fadeAndSlideFromBottom}.am-fade-and-slide-bottom.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-bottom.ng-leave{-webkit-animation-name:fadeAndSlideToBottom;animation-name:fadeAndSlideToBottom}.am-fade-and-slide-left{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-left.am-fade-and-slide-left-add,.am-fade-and-slide-left.ng-hide-remove,.am-fade-and-slide-left.ng-move{-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;-webkit-animation-name:fadeAndSlideFromLeft;animation-name:fadeAndSlideFromLeft}.am-fade-and-slide-left.am-fade-and-slide-left-remove,.am-fade-and-slide-left.ng-hide{-webkit-animation-name:fadeAndSlideToLeft;animation-name:fadeAndSlideToLeft}.am-fade-and-slide-left.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromLeft;animation-name:fadeAndSlideFromLeft}.am-fade-and-slide-left.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-left.ng-leave{-webkit-animation-name:fadeAndSlideToLeft;animation-name:fadeAndSlideToLeft}@-webkit-keyframes fadeAndSlideFromTop{from{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}to{opacity:1}}@keyframes fadeAndSlideFromTop{from{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToTop{from{opacity:1}to{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}}@keyframes fadeAndSlideToTop{from{opacity:1}to{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}}@-webkit-keyframes fadeAndSlideFromRight{from{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}to{opacity:1}}@keyframes fadeAndSlideFromRight{from{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToRight{from{opacity:1}to{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}}@keyframes fadeAndSlideToRight{from{opacity:1}to{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}}@-webkit-keyframes fadeAndSlideFromBottom{from{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}to{opacity:1}}@keyframes fadeAndSlideFromBottom{from{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToBottom{from{opacity:1}to{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}}@keyframes fadeAndSlideToBottom{from{opacity:1}to{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}}@-webkit-keyframes fadeAndSlideFromLeft{from{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}to{opacity:1}}@keyframes fadeAndSlideFromLeft{from{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToLeft{from{opacity:1}to{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}}@keyframes fadeAndSlideToLeft{from{opacity:1}to{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}}.am-fade{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;opacity:1}.am-fade.am-fade-add,.am-fade.ng-hide-remove,.am-fade.ng-move{-webkit-animation-name:fadeIn;animation-name:fadeIn}.am-fade.am-fade-remove,.am-fade.ng-hide{-webkit-animation-name:fadeOut;animation-name:fadeOut}.am-fade.ng-enter{visibility:hidden;-webkit-animation-name:fadeIn;animation-name:fadeIn}.am-fade.ng-enter.ng-enter-active{visibility:visible}.am-fade.ng-leave{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.modal-backdrop.am-fade,.aside-backdrop.am-fade{background:rgba(0,0,0,.5);-webkit-animation-duration:.15s;animation-duration:.15s}.am-flip-x{-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-flip-x.am-flip-x-add,.am-flip-x.ng-hide-remove,.am-flip-x.ng-move{-webkit-animation-name:flipInXBounce;animation-name:flipInXBounce}.am-flip-x.am-flip-x-remove,.am-flip-x.ng-hide{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x.ng-enter{visibility:hidden;-webkit-animation-name:flipInXBounce;animation-name:flipInXBounce}.am-flip-x.ng-enter.ng-enter-active{visibility:visible}.am-flip-x.ng-leave{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x-linear{-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-flip-x-linear.am-flip-x-add,.am-flip-x-linear.ng-hide-remove,.am-flip-x-linear.ng-move{-webkit-animation-name:flipInX;animation-name:flipInX}.am-flip-x-linear.am-flip-x-remove,.am-flip-x-linear.ng-hide{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x-linear.ng-enter{visibility:hidden;-webkit-animation-name:flipInX;animation-name:flipInX}.am-flip-x-linear.ng-enter.ng-enter-active{visibility:visible}.am-flip-x-linear.ng-leave{-webkit-animation-name:flipOutX;animation-name:flipOutX}@-webkit-keyframes flipInX{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@keyframes flipInX{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@-webkit-keyframes flipInXBounce{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}40%{-webkit-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@keyframes flipInXBounce{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}40%{-webkit-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@-webkit-keyframes flipOutX{from{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}to{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}}@keyframes flipOutX{from{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}to{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}}.am-slide-top{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-top.am-fade-and-slide-top-add,.am-slide-top.ng-hide-remove,.am-slide-top.ng-move{-webkit-animation-name:slideFromTop;animation-name:slideFromTop}.am-slide-top.am-fade-and-slide-top-remove,.am-slide-top.ng-hide{-webkit-animation-name:slideToTop;animation-name:slideToTop}.am-slide-top.ng-enter{visibility:hidden;-webkit-animation-name:slideFromTop;animation-name:slideFromTop}.am-slide-top.ng-enter.ng-enter-active{visibility:visible}.am-slide-top.ng-leave{-webkit-animation-name:slideToTop;animation-name:slideToTop}.am-slide-right{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-right.am-fade-and-slide-right-add,.am-slide-right.ng-hide-remove,.am-slide-right.ng-move{-webkit-animation-name:slideFromRight;animation-name:slideFromRight}.am-slide-right.am-fade-and-slide-right-remove,.am-slide-right.ng-hide{-webkit-animation-name:slideToRight;animation-name:slideToRight}.am-slide-right.ng-enter{visibility:hidden;-webkit-animation-name:slideFromRight;animation-name:slideFromRight}.am-slide-right.ng-enter.ng-enter-active{visibility:visible}.am-slide-right.ng-leave{-webkit-animation-name:slideToRight;animation-name:slideToRight}.am-slide-bottom{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-bottom.am-fade-and-slide-bottom-add,.am-slide-bottom.ng-hide-remove,.am-slide-bottom.ng-move{-webkit-animation-name:slideFromBottom;animation-name:slideFromBottom}.am-slide-bottom.am-fade-and-slide-bottom-remove,.am-slide-bottom.ng-hide{-webkit-animation-name:slideToBottom;animation-name:slideToBottom}.am-slide-bottom.ng-enter{visibility:hidden;-webkit-animation-name:slideFromBottom;animation-name:slideFromBottom}.am-slide-bottom.ng-enter.ng-enter-active{visibility:visible}.am-slide-bottom.ng-leave{-webkit-animation-name:slideToBottom;animation-name:slideToBottom}.am-slide-left{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-left.am-fade-and-slide-left-add,.am-slide-left.ng-hide-remove,.am-slide-left.ng-move{-webkit-animation-name:slideFromLeft;animation-name:slideFromLeft}.am-slide-left.am-fade-and-slide-left-remove,.am-slide-left.ng-hide{-webkit-animation-name:slideToLeft;animation-name:slideToLeft}.am-slide-left.ng-enter{visibility:hidden;-webkit-animation-name:slideFromLeft;animation-name:slideFromLeft}.am-slide-left.ng-enter.ng-enter-active{visibility:visible}.am-slide-left.ng-leave{-webkit-animation-name:slideToLeft;animation-name:slideToLeft}@-webkit-keyframes slideFromTop{from{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@keyframes slideFromTop{from{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@-webkit-keyframes slideToTop{to{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@keyframes slideToTop{to{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@-webkit-keyframes slideFromRight{from{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes slideFromRight{from{-webkit-transform:translateX(100%);transform:translateX(100%)}}@-webkit-keyframes slideToRight{to{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes slideToRight{to{-webkit-transform:translateX(100%);transform:translateX(100%)}}@-webkit-keyframes slideFromBottom{from{-webkit-transform:translateY(100%);transform:translateY(100%)}}@keyframes slideFromBottom{from{-webkit-transform:translateY(100%);transform:translateY(100%)}}@-webkit-keyframes slideToBottom{to{-webkit-transform:translateY(100%);transform:translateY(100%)}}@keyframes slideToBottom{to{-webkit-transform:translateY(100%);transform:translateY(100%)}}@-webkit-keyframes slideFromLeft{from{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes slideFromLeft{from{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@-webkit-keyframes slideToLeft{to{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes slideToLeft{to{-webkit-transform:translateX(-100%);transform:translateX(-100%)}} |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-scale { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-scale.ng-enter, |
| | | .am-fade-and-scale.am-fade-and-scale-add, |
| | | .am-fade-and-scale.ng-hide-remove, |
| | | .am-fade-and-scale.ng-move { |
| | | -webkit-animation-name: fadeAndScaleIn; |
| | | animation-name: fadeAndScaleIn; |
| | | } |
| | | .am-fade-and-scale.ng-leave, |
| | | .am-fade-and-scale.am-fade-and-scale-remove, |
| | | .am-fade-and-scale.ng-hide { |
| | | -webkit-animation-name: fadeAndScaleOut; |
| | | animation-name: fadeAndScaleOut; |
| | | } |
| | | .am-fade-and-scale.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndScaleIn; |
| | | animation-name: fadeAndScaleIn; |
| | | } |
| | | .am-fade-and-scale.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-scale.ng-leave { |
| | | -webkit-animation-name: fadeAndScaleOut; |
| | | animation-name: fadeAndScaleOut; |
| | | } |
| | | @-webkit-keyframes fadeAndScaleIn { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndScaleIn { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndScaleOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | } |
| | | @keyframes fadeAndScaleOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: scale(0.7); |
| | | transform: scale(0.7); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-scale{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-scale.ng-enter,.am-fade-and-scale.am-fade-and-scale-add,.am-fade-and-scale.ng-hide-remove,.am-fade-and-scale.ng-move{-webkit-animation-name:fadeAndScaleIn;animation-name:fadeAndScaleIn}.am-fade-and-scale.ng-leave,.am-fade-and-scale.am-fade-and-scale-remove,.am-fade-and-scale.ng-hide{-webkit-animation-name:fadeAndScaleOut;animation-name:fadeAndScaleOut}.am-fade-and-scale.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndScaleIn;animation-name:fadeAndScaleIn}.am-fade-and-scale.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-scale.ng-leave{-webkit-animation-name:fadeAndScaleOut;animation-name:fadeAndScaleOut}@-webkit-keyframes fadeAndScaleIn{from{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}to{opacity:1}}@keyframes fadeAndScaleIn{from{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}to{opacity:1}}@-webkit-keyframes fadeAndScaleOut{from{opacity:1}to{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}}@keyframes fadeAndScaleOut{from{opacity:1}to{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)}} |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-slide-top { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-top.am-fade-and-slide-top-add, |
| | | .am-fade-and-slide-top.ng-hide-remove, |
| | | .am-fade-and-slide-top.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromTop; |
| | | animation-name: fadeAndSlideFromTop; |
| | | } |
| | | .am-fade-and-slide-top.am-fade-and-slide-top-remove, |
| | | .am-fade-and-slide-top.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToTop; |
| | | animation-name: fadeAndSlideToTop; |
| | | } |
| | | .am-fade-and-slide-top.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromTop; |
| | | animation-name: fadeAndSlideFromTop; |
| | | } |
| | | .am-fade-and-slide-top.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-top.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToTop; |
| | | animation-name: fadeAndSlideToTop; |
| | | } |
| | | .am-fade-and-slide-right { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-right.am-fade-and-slide-right-add, |
| | | .am-fade-and-slide-right.ng-hide-remove, |
| | | .am-fade-and-slide-right.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromRight; |
| | | animation-name: fadeAndSlideFromRight; |
| | | } |
| | | .am-fade-and-slide-right.am-fade-and-slide-right-remove, |
| | | .am-fade-and-slide-right.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToRight; |
| | | animation-name: fadeAndSlideToRight; |
| | | } |
| | | .am-fade-and-slide-right.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromRight; |
| | | animation-name: fadeAndSlideFromRight; |
| | | } |
| | | .am-fade-and-slide-right.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-right.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToRight; |
| | | animation-name: fadeAndSlideToRight; |
| | | } |
| | | .am-fade-and-slide-bottom { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-bottom.am-fade-and-slide-bottom-add, |
| | | .am-fade-and-slide-bottom.ng-hide-remove, |
| | | .am-fade-and-slide-bottom.ng-move { |
| | | -webkit-animation-name: fadeAndSlideFromBottom; |
| | | animation-name: fadeAndSlideFromBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.am-fade-and-slide-bottom-remove, |
| | | .am-fade-and-slide-bottom.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToBottom; |
| | | animation-name: fadeAndSlideToBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromBottom; |
| | | animation-name: fadeAndSlideFromBottom; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-bottom.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToBottom; |
| | | animation-name: fadeAndSlideToBottom; |
| | | } |
| | | .am-fade-and-slide-left { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-fade-and-slide-left.am-fade-and-slide-left-add, |
| | | .am-fade-and-slide-left.ng-hide-remove, |
| | | .am-fade-and-slide-left.ng-move { |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | -webkit-animation-name: fadeAndSlideFromLeft; |
| | | animation-name: fadeAndSlideFromLeft; |
| | | } |
| | | .am-fade-and-slide-left.am-fade-and-slide-left-remove, |
| | | .am-fade-and-slide-left.ng-hide { |
| | | -webkit-animation-name: fadeAndSlideToLeft; |
| | | animation-name: fadeAndSlideToLeft; |
| | | } |
| | | .am-fade-and-slide-left.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeAndSlideFromLeft; |
| | | animation-name: fadeAndSlideFromLeft; |
| | | } |
| | | .am-fade-and-slide-left.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade-and-slide-left.ng-leave { |
| | | -webkit-animation-name: fadeAndSlideToLeft; |
| | | animation-name: fadeAndSlideToLeft; |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromTop { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromTop { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToTop { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToTop { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(-20%); |
| | | transform: translateY(-20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromRight { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromRight { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToRight { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToRight { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(20%); |
| | | transform: translateX(20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromBottom { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromBottom { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToBottom { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToBottom { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateY(20%); |
| | | transform: translateY(20%); |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideFromLeft { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideFromLeft { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeAndSlideToLeft { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | } |
| | | @keyframes fadeAndSlideToLeft { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: translateX(-20%); |
| | | transform: translateX(-20%); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade-and-slide-top{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-top.am-fade-and-slide-top-add,.am-fade-and-slide-top.ng-hide-remove,.am-fade-and-slide-top.ng-move{-webkit-animation-name:fadeAndSlideFromTop;animation-name:fadeAndSlideFromTop}.am-fade-and-slide-top.am-fade-and-slide-top-remove,.am-fade-and-slide-top.ng-hide{-webkit-animation-name:fadeAndSlideToTop;animation-name:fadeAndSlideToTop}.am-fade-and-slide-top.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromTop;animation-name:fadeAndSlideFromTop}.am-fade-and-slide-top.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-top.ng-leave{-webkit-animation-name:fadeAndSlideToTop;animation-name:fadeAndSlideToTop}.am-fade-and-slide-right{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-right.am-fade-and-slide-right-add,.am-fade-and-slide-right.ng-hide-remove,.am-fade-and-slide-right.ng-move{-webkit-animation-name:fadeAndSlideFromRight;animation-name:fadeAndSlideFromRight}.am-fade-and-slide-right.am-fade-and-slide-right-remove,.am-fade-and-slide-right.ng-hide{-webkit-animation-name:fadeAndSlideToRight;animation-name:fadeAndSlideToRight}.am-fade-and-slide-right.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromRight;animation-name:fadeAndSlideFromRight}.am-fade-and-slide-right.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-right.ng-leave{-webkit-animation-name:fadeAndSlideToRight;animation-name:fadeAndSlideToRight}.am-fade-and-slide-bottom{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-bottom.am-fade-and-slide-bottom-add,.am-fade-and-slide-bottom.ng-hide-remove,.am-fade-and-slide-bottom.ng-move{-webkit-animation-name:fadeAndSlideFromBottom;animation-name:fadeAndSlideFromBottom}.am-fade-and-slide-bottom.am-fade-and-slide-bottom-remove,.am-fade-and-slide-bottom.ng-hide{-webkit-animation-name:fadeAndSlideToBottom;animation-name:fadeAndSlideToBottom}.am-fade-and-slide-bottom.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromBottom;animation-name:fadeAndSlideFromBottom}.am-fade-and-slide-bottom.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-bottom.ng-leave{-webkit-animation-name:fadeAndSlideToBottom;animation-name:fadeAndSlideToBottom}.am-fade-and-slide-left{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-fade-and-slide-left.am-fade-and-slide-left-add,.am-fade-and-slide-left.ng-hide-remove,.am-fade-and-slide-left.ng-move{-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;-webkit-animation-name:fadeAndSlideFromLeft;animation-name:fadeAndSlideFromLeft}.am-fade-and-slide-left.am-fade-and-slide-left-remove,.am-fade-and-slide-left.ng-hide{-webkit-animation-name:fadeAndSlideToLeft;animation-name:fadeAndSlideToLeft}.am-fade-and-slide-left.ng-enter{visibility:hidden;-webkit-animation-name:fadeAndSlideFromLeft;animation-name:fadeAndSlideFromLeft}.am-fade-and-slide-left.ng-enter.ng-enter-active{visibility:visible}.am-fade-and-slide-left.ng-leave{-webkit-animation-name:fadeAndSlideToLeft;animation-name:fadeAndSlideToLeft}@-webkit-keyframes fadeAndSlideFromTop{from{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}to{opacity:1}}@keyframes fadeAndSlideFromTop{from{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToTop{from{opacity:1}to{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}}@keyframes fadeAndSlideToTop{from{opacity:1}to{opacity:0;-webkit-transform:translateY(-20%);transform:translateY(-20%)}}@-webkit-keyframes fadeAndSlideFromRight{from{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}to{opacity:1}}@keyframes fadeAndSlideFromRight{from{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToRight{from{opacity:1}to{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}}@keyframes fadeAndSlideToRight{from{opacity:1}to{opacity:0;-webkit-transform:translateX(20%);transform:translateX(20%)}}@-webkit-keyframes fadeAndSlideFromBottom{from{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}to{opacity:1}}@keyframes fadeAndSlideFromBottom{from{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToBottom{from{opacity:1}to{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}}@keyframes fadeAndSlideToBottom{from{opacity:1}to{opacity:0;-webkit-transform:translateY(20%);transform:translateY(20%)}}@-webkit-keyframes fadeAndSlideFromLeft{from{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}to{opacity:1}}@keyframes fadeAndSlideFromLeft{from{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}to{opacity:1}}@-webkit-keyframes fadeAndSlideToLeft{from{opacity:1}to{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}}@keyframes fadeAndSlideToLeft{from{opacity:1}to{opacity:0;-webkit-transform:translateX(-20%);transform:translateX(-20%)}} |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: linear; |
| | | animation-timing-function: linear; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | opacity: 1; |
| | | } |
| | | .am-fade.am-fade-add, |
| | | .am-fade.ng-hide-remove, |
| | | .am-fade.ng-move { |
| | | -webkit-animation-name: fadeIn; |
| | | animation-name: fadeIn; |
| | | } |
| | | .am-fade.am-fade-remove, |
| | | .am-fade.ng-hide { |
| | | -webkit-animation-name: fadeOut; |
| | | animation-name: fadeOut; |
| | | } |
| | | .am-fade.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: fadeIn; |
| | | animation-name: fadeIn; |
| | | } |
| | | .am-fade.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-fade.ng-leave { |
| | | -webkit-animation-name: fadeOut; |
| | | animation-name: fadeOut; |
| | | } |
| | | @-webkit-keyframes fadeIn { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @keyframes fadeIn { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | @-webkit-keyframes fadeOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | } |
| | | } |
| | | @keyframes fadeOut { |
| | | from { |
| | | opacity: 1; |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | } |
| | | } |
| | | .modal-backdrop.am-fade, |
| | | .aside-backdrop.am-fade { |
| | | background: rgba(0, 0, 0, 0.5); |
| | | -webkit-animation-duration: 0.15s; |
| | | animation-duration: 0.15s; |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-fade{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;opacity:1}.am-fade.am-fade-add,.am-fade.ng-hide-remove,.am-fade.ng-move{-webkit-animation-name:fadeIn;animation-name:fadeIn}.am-fade.am-fade-remove,.am-fade.ng-hide{-webkit-animation-name:fadeOut;animation-name:fadeOut}.am-fade.ng-enter{visibility:hidden;-webkit-animation-name:fadeIn;animation-name:fadeIn}.am-fade.ng-enter.ng-enter-active{visibility:visible}.am-fade.ng-leave{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.modal-backdrop.am-fade,.aside-backdrop.am-fade{background:rgba(0,0,0,.5);-webkit-animation-duration:.15s;animation-duration:.15s} |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-flip-x { |
| | | -webkit-animation-duration: 0.4s; |
| | | animation-duration: 0.4s; |
| | | -webkit-animation-timing-function: ease; |
| | | animation-timing-function: ease; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-flip-x.am-flip-x-add, |
| | | .am-flip-x.ng-hide-remove, |
| | | .am-flip-x.ng-move { |
| | | -webkit-animation-name: flipInXBounce; |
| | | animation-name: flipInXBounce; |
| | | } |
| | | .am-flip-x.am-flip-x-remove, |
| | | .am-flip-x.ng-hide { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: flipInXBounce; |
| | | animation-name: flipInXBounce; |
| | | } |
| | | .am-flip-x.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-flip-x.ng-leave { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x-linear { |
| | | -webkit-animation-duration: 0.4s; |
| | | animation-duration: 0.4s; |
| | | -webkit-animation-timing-function: ease; |
| | | animation-timing-function: ease; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-flip-x-linear.am-flip-x-add, |
| | | .am-flip-x-linear.ng-hide-remove, |
| | | .am-flip-x-linear.ng-move { |
| | | -webkit-animation-name: flipInX; |
| | | animation-name: flipInX; |
| | | } |
| | | .am-flip-x-linear.am-flip-x-remove, |
| | | .am-flip-x-linear.ng-hide { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | .am-flip-x-linear.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: flipInX; |
| | | animation-name: flipInX; |
| | | } |
| | | .am-flip-x-linear.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-flip-x-linear.ng-leave { |
| | | -webkit-animation-name: flipOutX; |
| | | animation-name: flipOutX; |
| | | } |
| | | @-webkit-keyframes flipInX { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @keyframes flipInX { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @-webkit-keyframes flipInXBounce { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | 40% { |
| | | -webkit-transform: perspective(400px) rotateX(-10deg); |
| | | transform: perspective(400px) rotateX(-10deg); |
| | | } |
| | | 70% { |
| | | -webkit-transform: perspective(400px) rotateX(10deg); |
| | | transform: perspective(400px) rotateX(10deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @keyframes flipInXBounce { |
| | | from { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | 40% { |
| | | -webkit-transform: perspective(400px) rotateX(-10deg); |
| | | transform: perspective(400px) rotateX(-10deg); |
| | | } |
| | | 70% { |
| | | -webkit-transform: perspective(400px) rotateX(10deg); |
| | | transform: perspective(400px) rotateX(10deg); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | } |
| | | @-webkit-keyframes flipOutX { |
| | | from { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | } |
| | | @keyframes flipOutX { |
| | | from { |
| | | opacity: 1; |
| | | -webkit-transform: perspective(400px) rotateX(0deg); |
| | | transform: perspective(400px) rotateX(0deg); |
| | | } |
| | | to { |
| | | opacity: 0; |
| | | -webkit-transform: perspective(400px) rotateX(90deg); |
| | | transform: perspective(400px) rotateX(90deg); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-flip-x{-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-flip-x.am-flip-x-add,.am-flip-x.ng-hide-remove,.am-flip-x.ng-move{-webkit-animation-name:flipInXBounce;animation-name:flipInXBounce}.am-flip-x.am-flip-x-remove,.am-flip-x.ng-hide{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x.ng-enter{visibility:hidden;-webkit-animation-name:flipInXBounce;animation-name:flipInXBounce}.am-flip-x.ng-enter.ng-enter-active{visibility:visible}.am-flip-x.ng-leave{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x-linear{-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-timing-function:ease;animation-timing-function:ease;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-flip-x-linear.am-flip-x-add,.am-flip-x-linear.ng-hide-remove,.am-flip-x-linear.ng-move{-webkit-animation-name:flipInX;animation-name:flipInX}.am-flip-x-linear.am-flip-x-remove,.am-flip-x-linear.ng-hide{-webkit-animation-name:flipOutX;animation-name:flipOutX}.am-flip-x-linear.ng-enter{visibility:hidden;-webkit-animation-name:flipInX;animation-name:flipInX}.am-flip-x-linear.ng-enter.ng-enter-active{visibility:visible}.am-flip-x-linear.ng-leave{-webkit-animation-name:flipOutX;animation-name:flipOutX}@-webkit-keyframes flipInX{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@keyframes flipInX{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@-webkit-keyframes flipInXBounce{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}40%{-webkit-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@keyframes flipInXBounce{from{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}40%{-webkit-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}to{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}}@-webkit-keyframes flipOutX{from{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}to{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}}@keyframes flipOutX{from{opacity:1;-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg)}to{opacity:0;-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg)}} |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-slide-top { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-top.am-fade-and-slide-top-add, |
| | | .am-slide-top.ng-hide-remove, |
| | | .am-slide-top.ng-move { |
| | | -webkit-animation-name: slideFromTop; |
| | | animation-name: slideFromTop; |
| | | } |
| | | .am-slide-top.am-fade-and-slide-top-remove, |
| | | .am-slide-top.ng-hide { |
| | | -webkit-animation-name: slideToTop; |
| | | animation-name: slideToTop; |
| | | } |
| | | .am-slide-top.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromTop; |
| | | animation-name: slideFromTop; |
| | | } |
| | | .am-slide-top.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-top.ng-leave { |
| | | -webkit-animation-name: slideToTop; |
| | | animation-name: slideToTop; |
| | | } |
| | | .am-slide-right { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-right.am-fade-and-slide-right-add, |
| | | .am-slide-right.ng-hide-remove, |
| | | .am-slide-right.ng-move { |
| | | -webkit-animation-name: slideFromRight; |
| | | animation-name: slideFromRight; |
| | | } |
| | | .am-slide-right.am-fade-and-slide-right-remove, |
| | | .am-slide-right.ng-hide { |
| | | -webkit-animation-name: slideToRight; |
| | | animation-name: slideToRight; |
| | | } |
| | | .am-slide-right.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromRight; |
| | | animation-name: slideFromRight; |
| | | } |
| | | .am-slide-right.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-right.ng-leave { |
| | | -webkit-animation-name: slideToRight; |
| | | animation-name: slideToRight; |
| | | } |
| | | .am-slide-bottom { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-bottom.am-fade-and-slide-bottom-add, |
| | | .am-slide-bottom.ng-hide-remove, |
| | | .am-slide-bottom.ng-move { |
| | | -webkit-animation-name: slideFromBottom; |
| | | animation-name: slideFromBottom; |
| | | } |
| | | .am-slide-bottom.am-fade-and-slide-bottom-remove, |
| | | .am-slide-bottom.ng-hide { |
| | | -webkit-animation-name: slideToBottom; |
| | | animation-name: slideToBottom; |
| | | } |
| | | .am-slide-bottom.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromBottom; |
| | | animation-name: slideFromBottom; |
| | | } |
| | | .am-slide-bottom.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-bottom.ng-leave { |
| | | -webkit-animation-name: slideToBottom; |
| | | animation-name: slideToBottom; |
| | | } |
| | | .am-slide-left { |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-timing-function: ease-in-out; |
| | | animation-timing-function: ease-in-out; |
| | | -webkit-animation-fill-mode: backwards; |
| | | animation-fill-mode: backwards; |
| | | } |
| | | .am-slide-left.am-fade-and-slide-left-add, |
| | | .am-slide-left.ng-hide-remove, |
| | | .am-slide-left.ng-move { |
| | | -webkit-animation-name: slideFromLeft; |
| | | animation-name: slideFromLeft; |
| | | } |
| | | .am-slide-left.am-fade-and-slide-left-remove, |
| | | .am-slide-left.ng-hide { |
| | | -webkit-animation-name: slideToLeft; |
| | | animation-name: slideToLeft; |
| | | } |
| | | .am-slide-left.ng-enter { |
| | | visibility: hidden; |
| | | -webkit-animation-name: slideFromLeft; |
| | | animation-name: slideFromLeft; |
| | | } |
| | | .am-slide-left.ng-enter.ng-enter-active { |
| | | visibility: visible; |
| | | } |
| | | .am-slide-left.ng-leave { |
| | | -webkit-animation-name: slideToLeft; |
| | | animation-name: slideToLeft; |
| | | } |
| | | @-webkit-keyframes slideFromTop { |
| | | from { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @keyframes slideFromTop { |
| | | from { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToTop { |
| | | to { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @keyframes slideToTop { |
| | | to { |
| | | -webkit-transform: translateY(-100%); |
| | | transform: translateY(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromRight { |
| | | from { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @keyframes slideFromRight { |
| | | from { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToRight { |
| | | to { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @keyframes slideToRight { |
| | | to { |
| | | -webkit-transform: translateX(100%); |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromBottom { |
| | | from { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @keyframes slideFromBottom { |
| | | from { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToBottom { |
| | | to { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @keyframes slideToBottom { |
| | | to { |
| | | -webkit-transform: translateY(100%); |
| | | transform: translateY(100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideFromLeft { |
| | | from { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @keyframes slideFromLeft { |
| | | from { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @-webkit-keyframes slideToLeft { |
| | | to { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
| | | @keyframes slideToLeft { |
| | | to { |
| | | -webkit-transform: translateX(-100%); |
| | | transform: translateX(-100%); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-motion |
| | | * @version v0.3.2 - 2014-02-11 |
| | | * @link https://github.com/mgcrea/angular-motion |
| | | * @author Olivier Louvignes <olivier@mg-crea.com> |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | .am-slide-top{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-top.am-fade-and-slide-top-add,.am-slide-top.ng-hide-remove,.am-slide-top.ng-move{-webkit-animation-name:slideFromTop;animation-name:slideFromTop}.am-slide-top.am-fade-and-slide-top-remove,.am-slide-top.ng-hide{-webkit-animation-name:slideToTop;animation-name:slideToTop}.am-slide-top.ng-enter{visibility:hidden;-webkit-animation-name:slideFromTop;animation-name:slideFromTop}.am-slide-top.ng-enter.ng-enter-active{visibility:visible}.am-slide-top.ng-leave{-webkit-animation-name:slideToTop;animation-name:slideToTop}.am-slide-right{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-right.am-fade-and-slide-right-add,.am-slide-right.ng-hide-remove,.am-slide-right.ng-move{-webkit-animation-name:slideFromRight;animation-name:slideFromRight}.am-slide-right.am-fade-and-slide-right-remove,.am-slide-right.ng-hide{-webkit-animation-name:slideToRight;animation-name:slideToRight}.am-slide-right.ng-enter{visibility:hidden;-webkit-animation-name:slideFromRight;animation-name:slideFromRight}.am-slide-right.ng-enter.ng-enter-active{visibility:visible}.am-slide-right.ng-leave{-webkit-animation-name:slideToRight;animation-name:slideToRight}.am-slide-bottom{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-bottom.am-fade-and-slide-bottom-add,.am-slide-bottom.ng-hide-remove,.am-slide-bottom.ng-move{-webkit-animation-name:slideFromBottom;animation-name:slideFromBottom}.am-slide-bottom.am-fade-and-slide-bottom-remove,.am-slide-bottom.ng-hide{-webkit-animation-name:slideToBottom;animation-name:slideToBottom}.am-slide-bottom.ng-enter{visibility:hidden;-webkit-animation-name:slideFromBottom;animation-name:slideFromBottom}.am-slide-bottom.ng-enter.ng-enter-active{visibility:visible}.am-slide-bottom.ng-leave{-webkit-animation-name:slideToBottom;animation-name:slideToBottom}.am-slide-left{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}.am-slide-left.am-fade-and-slide-left-add,.am-slide-left.ng-hide-remove,.am-slide-left.ng-move{-webkit-animation-name:slideFromLeft;animation-name:slideFromLeft}.am-slide-left.am-fade-and-slide-left-remove,.am-slide-left.ng-hide{-webkit-animation-name:slideToLeft;animation-name:slideToLeft}.am-slide-left.ng-enter{visibility:hidden;-webkit-animation-name:slideFromLeft;animation-name:slideFromLeft}.am-slide-left.ng-enter.ng-enter-active{visibility:visible}.am-slide-left.ng-leave{-webkit-animation-name:slideToLeft;animation-name:slideToLeft}@-webkit-keyframes slideFromTop{from{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@keyframes slideFromTop{from{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@-webkit-keyframes slideToTop{to{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@keyframes slideToTop{to{-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@-webkit-keyframes slideFromRight{from{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes slideFromRight{from{-webkit-transform:translateX(100%);transform:translateX(100%)}}@-webkit-keyframes slideToRight{to{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes slideToRight{to{-webkit-transform:translateX(100%);transform:translateX(100%)}}@-webkit-keyframes slideFromBottom{from{-webkit-transform:translateY(100%);transform:translateY(100%)}}@keyframes slideFromBottom{from{-webkit-transform:translateY(100%);transform:translateY(100%)}}@-webkit-keyframes slideToBottom{to{-webkit-transform:translateY(100%);transform:translateY(100%)}}@keyframes slideToBottom{to{-webkit-transform:translateY(100%);transform:translateY(100%)}}@-webkit-keyframes slideFromLeft{from{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes slideFromLeft{from{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@-webkit-keyframes slideToLeft{to{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes slideToLeft{to{-webkit-transform:translateX(-100%);transform:translateX(-100%)}} |
New file |
| | |
| | | /*! |
| | | angular-xeditable - 0.1.8 |
| | | Edit-in-place for angular.js |
| | | Build date: 2014-01-10 |
| | | */ |
| | | |
| | | .editable-wrap{display:inline-block;white-space:nowrap;margin:0}.editable-wrap .editable-controls,.editable-wrap .editable-error{margin-bottom:0}.editable-wrap .editable-controls>input,.editable-wrap .editable-controls>select,.editable-wrap .editable-controls>textarea{margin-bottom:0}.editable-wrap .editable-input{display:inline-block}.editable-buttons{display:inline-block;vertical-align:top}.editable-buttons button{margin-left:5px}.editable-input.editable-has-buttons{width:auto}.editable-bstime .editable-input input[type=text]{width:46px}.editable-bstime .well-small{margin-bottom:0;padding:10px}.editable-range output{display:inline-block;min-width:30px;vertical-align:top;text-align:center}.editable-color input[type=color]{width:50px}.editable-checkbox label span,.editable-checklist label span,.editable-radiolist label span{margin-left:7px;margin-right:10px}.editable-hide{display:none!important}.editable-click,a.editable-click{text-decoration:none;color:#428bca;border-bottom:dashed 1px #428bca}.editable-click:hover,a.editable-click:hover{text-decoration:none;color:#2a6496;border-bottom-color:#2a6496}.editable-empty,.editable-empty:hover,.editable-empty:focus,a.editable-empty,a.editable-empty:hover,a.editable-empty:focus{font-style:italic;color:#D14;text-decoration:none} |
New file |
| | |
| | | /*! |
| | | * Bootstrap v3.1.1 (http://getbootstrap.com) |
| | | * Copyright 2011-2014 Twitter, Inc. |
| | | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
| | | */ |
| | | |
| | | .btn-default, |
| | | .btn-primary, |
| | | .btn-success, |
| | | .btn-info, |
| | | .btn-warning, |
| | | .btn-danger { |
| | | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); |
| | | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); |
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); |
| | | } |
| | | .btn-default:active, |
| | | .btn-primary:active, |
| | | .btn-success:active, |
| | | .btn-info:active, |
| | | .btn-warning:active, |
| | | .btn-danger:active, |
| | | .btn-default.active, |
| | | .btn-primary.active, |
| | | .btn-success.active, |
| | | .btn-info.active, |
| | | .btn-warning.active, |
| | | .btn-danger.active { |
| | | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); |
| | | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); |
| | | } |
| | | .btn:active, |
| | | .btn.active { |
| | | background-image: none; |
| | | } |
| | | .btn-default { |
| | | text-shadow: 0 1px 0 #fff; |
| | | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); |
| | | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #dbdbdb; |
| | | border-color: #ccc; |
| | | } |
| | | .btn-default:hover, |
| | | .btn-default:focus { |
| | | background-color: #e0e0e0; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-default:active, |
| | | .btn-default.active { |
| | | background-color: #e0e0e0; |
| | | border-color: #dbdbdb; |
| | | } |
| | | .btn-primary { |
| | | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); |
| | | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #2b669a; |
| | | } |
| | | .btn-primary:hover, |
| | | .btn-primary:focus { |
| | | background-color: #2d6ca2; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-primary:active, |
| | | .btn-primary.active { |
| | | background-color: #2d6ca2; |
| | | border-color: #2b669a; |
| | | } |
| | | .btn-success { |
| | | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); |
| | | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #3e8f3e; |
| | | } |
| | | .btn-success:hover, |
| | | .btn-success:focus { |
| | | background-color: #419641; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-success:active, |
| | | .btn-success.active { |
| | | background-color: #419641; |
| | | border-color: #3e8f3e; |
| | | } |
| | | .btn-info { |
| | | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); |
| | | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #28a4c9; |
| | | } |
| | | .btn-info:hover, |
| | | .btn-info:focus { |
| | | background-color: #2aabd2; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-info:active, |
| | | .btn-info.active { |
| | | background-color: #2aabd2; |
| | | border-color: #28a4c9; |
| | | } |
| | | .btn-warning { |
| | | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); |
| | | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #e38d13; |
| | | } |
| | | .btn-warning:hover, |
| | | .btn-warning:focus { |
| | | background-color: #eb9316; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-warning:active, |
| | | .btn-warning.active { |
| | | background-color: #eb9316; |
| | | border-color: #e38d13; |
| | | } |
| | | .btn-danger { |
| | | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); |
| | | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-color: #b92c28; |
| | | } |
| | | .btn-danger:hover, |
| | | .btn-danger:focus { |
| | | background-color: #c12e2a; |
| | | background-position: 0 -15px; |
| | | } |
| | | .btn-danger:active, |
| | | .btn-danger.active { |
| | | background-color: #c12e2a; |
| | | border-color: #b92c28; |
| | | } |
| | | .thumbnail, |
| | | .img-thumbnail { |
| | | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
| | | } |
| | | .dropdown-menu > li > a:hover, |
| | | .dropdown-menu > li > a:focus { |
| | | background-color: #e8e8e8; |
| | | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
| | | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .dropdown-menu > .active > a, |
| | | .dropdown-menu > .active > a:hover, |
| | | .dropdown-menu > .active > a:focus { |
| | | background-color: #357ebd; |
| | | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); |
| | | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .navbar-default { |
| | | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); |
| | | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | border-radius: 4px; |
| | | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); |
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); |
| | | } |
| | | .navbar-default .navbar-nav > .active > a { |
| | | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); |
| | | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); |
| | | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); |
| | | } |
| | | .navbar-brand, |
| | | .navbar-nav > li > a { |
| | | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); |
| | | } |
| | | .navbar-inverse { |
| | | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); |
| | | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .navbar-inverse .navbar-nav > .active > a { |
| | | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); |
| | | background-image: linear-gradient(to bottom, #222 0%, #282828 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); |
| | | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); |
| | | } |
| | | .navbar-inverse .navbar-brand, |
| | | .navbar-inverse .navbar-nav > li > a { |
| | | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); |
| | | } |
| | | .navbar-static-top, |
| | | .navbar-fixed-top, |
| | | .navbar-fixed-bottom { |
| | | border-radius: 0; |
| | | } |
| | | .alert { |
| | | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); |
| | | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); |
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); |
| | | } |
| | | .alert-success { |
| | | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); |
| | | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #b2dba1; |
| | | } |
| | | .alert-info { |
| | | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); |
| | | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #9acfea; |
| | | } |
| | | .alert-warning { |
| | | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); |
| | | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #f5e79e; |
| | | } |
| | | .alert-danger { |
| | | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); |
| | | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #dca7a7; |
| | | } |
| | | .progress { |
| | | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); |
| | | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .progress-bar { |
| | | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); |
| | | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .progress-bar-success { |
| | | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); |
| | | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .progress-bar-info { |
| | | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); |
| | | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .progress-bar-warning { |
| | | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); |
| | | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .progress-bar-danger { |
| | | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); |
| | | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .list-group { |
| | | border-radius: 4px; |
| | | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
| | | } |
| | | .list-group-item.active, |
| | | .list-group-item.active:hover, |
| | | .list-group-item.active:focus { |
| | | text-shadow: 0 -1px 0 #3071a9; |
| | | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); |
| | | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #3278b3; |
| | | } |
| | | .panel { |
| | | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); |
| | | } |
| | | .panel-default > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
| | | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .panel-primary > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); |
| | | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .panel-success > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); |
| | | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .panel-info > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); |
| | | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .panel-warning > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); |
| | | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .panel-danger > .panel-heading { |
| | | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); |
| | | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | } |
| | | .well { |
| | | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); |
| | | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); |
| | | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); |
| | | background-repeat: repeat-x; |
| | | border-color: #dcdcdc; |
| | | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); |
| | | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); |
| | | } |
| | | /*# sourceMappingURL=bootstrap-theme.css.map */ |
New file |
| | |
| | | {"version":3,"sources":["less/theme.less","less/mixins.less"],"names":[],"mappings":"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","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n\n// WebKit-style focus\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n\n// Center-align a block level element\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n\n// Sizing shortcuts\n.size(@width; @height) {\n width: @width;\n height: @height;\n}\n.square(@size) {\n .size(@size; @size);\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n -webkit-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n// Transformations\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n transform: translate(@x, @y);\n}\n.skew(@x; @y) {\n -webkit-transform: skew(@x, @y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n transform: skew(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n resize: @direction; // Options: horizontal, vertical, both\n overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n\n\n\n// GRADIENTS\n// --------------------------------------------------\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n\n// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n\n// Panels\n// -------------------------\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse .panel-body {\n border-top-color: @border;\n }\n }\n & > .panel-footer {\n + .panel-collapse .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n\n// Alerts\n// -------------------------\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n\n// Tables\n// -------------------------\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:hover,\n &:focus,\n &:active,\n &.active,\n .open .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 8%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n// -------------------------\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n\n// Pagination\n// -------------------------\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n\n// Labels\n// -------------------------\n.label-variant(@color) {\n background-color: @color;\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n\n// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n.progress-bar-variant(@color) {\n background-color: @color;\n .progress-striped & {\n #gradient > .striped();\n }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n"]} |
New file |
| | |
| | | /*! |
| | | * Bootstrap v3.1.1 (http://getbootstrap.com) |
| | | * Copyright 2011-2014 Twitter, Inc. |
| | | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
| | | */ |
| | | |
| | | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} |
New file |
| | |
| | | {"version":3,"sources":["less/normalize.less","less/print.less","less/scaffolding.less","less/mixins.less","less/variables.less","less/thumbnails.less","less/carousel.less","less/type.less","less/code.less","less/grid.less","less/tables.less","less/forms.less","less/buttons.less","less/button-groups.less","less/component-animations.less","less/glyphicons.less","less/dropdowns.less","less/input-groups.less","less/navs.less","less/navbar.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/pager.less","less/labels.less","less/badges.less","less/jumbotron.less","less/alerts.less","less/progress-bars.less","less/media.less","less/list-group.less","less/panels.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/responsive-utilities.less"],"names":[],"mappings":"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","sourcesContent":["/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n// user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined in IE 8/9.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9.\n// Hide the `template` element in IE, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9, Safari 5, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari 5 and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari 5, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow displayed oddly in IE 9.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8+, and Opera\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\n// (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; // 2\n box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}","//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n * {\n text-shadow: none !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links for images, or javascript/internal links\n a[href^=\"javascript:\"]:after,\n a[href^=\"#\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .table {\n td,\n th {\n background-color: #fff !important;\n }\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n}\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 62.5%;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n","//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n\n// WebKit-style focus\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n\n// Center-align a block level element\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n\n// Sizing shortcuts\n.size(@width; @height) {\n width: @width;\n height: @height;\n}\n.square(@size) {\n .size(@size; @size);\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n -webkit-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n// Transformations\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n transform: translate(@x, @y);\n}\n.skew(@x; @y) {\n -webkit-transform: skew(@x, @y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n transform: skew(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n resize: @direction; // Options: horizontal, vertical, both\n overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n\n\n\n// GRADIENTS\n// --------------------------------------------------\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n\n// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n\n// Panels\n// -------------------------\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse .panel-body {\n border-top-color: @border;\n }\n }\n & > .panel-footer {\n + .panel-collapse .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n\n// Alerts\n// -------------------------\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n\n// Tables\n// -------------------------\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:hover,\n &:focus,\n &:active,\n &.active,\n .open .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 8%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n// -------------------------\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n\n// Pagination\n// -------------------------\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n\n// Labels\n// -------------------------\n.label-variant(@color) {\n background-color: @color;\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n\n// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n.progress-bar-variant(@color) {\n background-color: @color;\n .progress-striped & {\n #gradient > .striped();\n }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Variables\n// --------------------------------------------------\n\n\n//== Colors\n//\n//## Gray and brand colors for use across Bootstrap.\n\n@gray-darker: lighten(#000, 13.5%); // #222\n@gray-dark: lighten(#000, 20%); // #333\n@gray: lighten(#000, 33.5%); // #555\n@gray-light: lighten(#000, 60%); // #999\n@gray-lighter: lighten(#000, 93.5%); // #eee\n\n@brand-primary: #428bca;\n@brand-success: #5cb85c;\n@brand-info: #5bc0de;\n@brand-warning: #f0ad4e;\n@brand-danger: #d9534f;\n\n\n//== Scaffolding\n//\n// ## Settings for some of the most global styles.\n\n//** Background color for `<body>`.\n@body-bg: #fff;\n//** Global text color on `<body>`.\n@text-color: @gray-dark;\n\n//** Global textual link color.\n@link-color: @brand-primary;\n//** Link hover color set via `darken()` function.\n@link-hover-color: darken(@link-color, 15%);\n\n\n//== Typography\n//\n//## Font, line-height, and color for body text, headings, and more.\n\n@font-family-sans-serif: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@font-family-serif: Georgia, \"Times New Roman\", Times, serif;\n//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.\n@font-family-monospace: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n@font-family-base: @font-family-sans-serif;\n\n@font-size-base: 14px;\n@font-size-large: ceil((@font-size-base * 1.25)); // ~18px\n@font-size-small: ceil((@font-size-base * 0.85)); // ~12px\n\n@font-size-h1: floor((@font-size-base * 2.6)); // ~36px\n@font-size-h2: floor((@font-size-base * 2.15)); // ~30px\n@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px\n@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px\n@font-size-h5: @font-size-base;\n@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px\n\n//** Unit-less `line-height` for use in components like buttons.\n@line-height-base: 1.428571429; // 20/14\n//** Computed \"line-height\" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.\n@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px\n\n//** By default, this inherits from the `<body>`.\n@headings-font-family: inherit;\n@headings-font-weight: 500;\n@headings-line-height: 1.1;\n@headings-color: inherit;\n\n\n//-- Iconography\n//\n//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.\n\n@icon-font-path: \"../fonts/\";\n@icon-font-name: \"glyphicons-halflings-regular\";\n@icon-font-svg-id: \"glyphicons_halflingsregular\";\n\n//== Components\n//\n//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).\n\n@padding-base-vertical: 6px;\n@padding-base-horizontal: 12px;\n\n@padding-large-vertical: 10px;\n@padding-large-horizontal: 16px;\n\n@padding-small-vertical: 5px;\n@padding-small-horizontal: 10px;\n\n@padding-xs-vertical: 1px;\n@padding-xs-horizontal: 5px;\n\n@line-height-large: 1.33;\n@line-height-small: 1.5;\n\n@border-radius-base: 4px;\n@border-radius-large: 6px;\n@border-radius-small: 3px;\n\n//** Global color for active items (e.g., navs or dropdowns).\n@component-active-color: #fff;\n//** Global background color for active items (e.g., navs or dropdowns).\n@component-active-bg: @brand-primary;\n\n//** Width of the `border` for generating carets that indicator dropdowns.\n@caret-width-base: 4px;\n//** Carets increase slightly in size for larger components.\n@caret-width-large: 5px;\n\n\n//== Tables\n//\n//## Customizes the `.table` component with basic values, each used across all table variations.\n\n//** Padding for `<th>`s and `<td>`s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: #f5f5f5;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: #ddd;\n\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight: normal;\n\n@btn-default-color: #333;\n@btn-default-bg: #fff;\n@btn-default-border: #ccc;\n\n@btn-primary-color: #fff;\n@btn-primary-bg: @brand-primary;\n@btn-primary-border: darken(@btn-primary-bg, 5%);\n\n@btn-success-color: #fff;\n@btn-success-bg: @brand-success;\n@btn-success-border: darken(@btn-success-bg, 5%);\n\n@btn-info-color: #fff;\n@btn-info-bg: @brand-info;\n@btn-info-border: darken(@btn-info-bg, 5%);\n\n@btn-warning-color: #fff;\n@btn-warning-bg: @brand-warning;\n@btn-warning-border: darken(@btn-warning-bg, 5%);\n\n@btn-danger-color: #fff;\n@btn-danger-bg: @brand-danger;\n@btn-danger-border: darken(@btn-danger-bg, 5%);\n\n@btn-link-disabled-color: @gray-light;\n\n\n//== Forms\n//\n//##\n\n//** `<input>` background color\n@input-bg: #fff;\n//** `<input disabled>` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for `<input>`s\n@input-color: @gray;\n//** `<input>` border color\n@input-border: #ccc;\n//** `<input>` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color: @gray-dark;\n@legend-border-color: #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar: 1000;\n@zindex-dropdown: 1000;\n@zindex-popover: 1010;\n@zindex-tooltip: 1030;\n@zindex-navbar-fixed: 1030;\n@zindex-modal-background: 1040;\n@zindex-modal: 1050;\n\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\n@navbar-border-radius: @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color: #777;\n@navbar-default-link-hover-color: #333;\n@navbar-default-link-hover-bg: transparent;\n@navbar-default-link-active-color: #555;\n@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);\n@navbar-default-link-disabled-color: #ccc;\n@navbar-default-link-disabled-bg: transparent;\n\n// Navbar brand label\n@navbar-default-brand-color: @navbar-default-link-color;\n@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);\n@navbar-default-brand-hover-bg: transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg: #ddd;\n@navbar-default-toggle-icon-bar-bg: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color: @gray-light;\n@navbar-inverse-bg: #222;\n@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color: @gray-light;\n@navbar-inverse-link-hover-color: #fff;\n@navbar-inverse-link-hover-bg: transparent;\n@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color: #444;\n@navbar-inverse-link-disabled-bg: transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color: @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color: #fff;\n@navbar-inverse-brand-hover-bg: transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg: #333;\n@navbar-inverse-toggle-icon-bar-bg: #fff;\n@navbar-inverse-toggle-border-color: #333;\n\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding: 10px 15px;\n@nav-link-hover-bg: @gray-lighter;\n\n@nav-disabled-link-color: @gray-light;\n@nav-disabled-link-hover-color: @gray-light;\n\n@nav-open-link-hover-color: #fff;\n\n//== Tabs\n@nav-tabs-border-color: #ddd;\n\n@nav-tabs-link-hover-border-color: @gray-lighter;\n\n@nav-tabs-active-link-hover-bg: @body-bg;\n@nav-tabs-active-link-hover-color: @gray;\n@nav-tabs-active-link-hover-border-color: #ddd;\n\n@nav-tabs-justified-link-border-color: #ddd;\n@nav-tabs-justified-active-link-border-color: @body-bg;\n\n//== Pills\n@nav-pills-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding: 15px;\n@alert-border-radius: @border-radius-base;\n@alert-link-font-weight: bold;\n\n@alert-success-bg: @state-success-bg;\n@alert-success-text: @state-success-text;\n@alert-success-border: @state-success-border;\n\n@alert-info-bg: @state-info-bg;\n@alert-info-text: @state-info-text;\n@alert-info-border: @state-info-border;\n\n@alert-warning-bg: @state-warning-bg;\n@alert-warning-text: @state-warning-text;\n@alert-warning-border: @state-warning-border;\n\n@alert-danger-bg: @state-danger-bg;\n@alert-danger-text: @state-danger-text;\n@alert-danger-border: @state-danger-border;\n\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\n@panel-footer-bg: #f5f5f5;\n\n@panel-default-text: @gray-dark;\n@panel-default-border: #ddd;\n@panel-default-heading-bg: #f5f5f5;\n\n@panel-primary-text: #fff;\n@panel-primary-border: @brand-primary;\n@panel-primary-heading-bg: @brand-primary;\n\n@panel-success-text: @state-success-text;\n@panel-success-border: @state-success-border;\n@panel-success-heading-bg: @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text: @state-warning-text;\n@panel-warning-border: @state-warning-border;\n@panel-warning-heading-bg: @state-warning-bg;\n\n@panel-danger-text: @state-danger-text;\n@panel-danger-border: @state-danger-border;\n@panel-danger-heading-bg: @state-danger-bg;\n\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\n@badge-active-bg: #fff;\n\n@badge-font-weight: bold;\n@badge-line-height: 1;\n@badge-border-radius: 10px;\n\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color: #fff;\n@carousel-control-width: 15%;\n@carousel-control-opacity: .5;\n@carousel-control-font-size: 20px;\n\n@carousel-indicator-active-bg: #fff;\n@carousel-indicator-border-color: #fff;\n\n@carousel-caption-color: #fff;\n\n\n//== Close\n//\n//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n }\n\n > .active,\n > .next,\n > .prev { display: block; }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: none;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n margin-left: -10px;\n font-family: serif;\n }\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n margin-left: -15px;\n font-size: 30px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n .dl-horizontal {\n dt {\n float: left;\n width: (@component-offset-horizontal - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @component-offset-horizontal;\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n white-space: nowrap;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n max-width: 100%;\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: @screen-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; /* IE8-9 */\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\n\ninput[type=\"date\"] {\n line-height: @input-height-base;\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n padding-left: 20px;\n label {\n display: inline;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n float: left;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n margin-bottom: 0; // Remove default margin from `p`\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match (which also avoids\n // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of labels, radios, and checkboxes\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n cursor: pointer;\n border-radius: 0;\n\n &,\n &:active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n padding-left: 0;\n padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n &:focus {\n // Remove focus outline when dropdown JS adds it after closing the menu\n outline: none;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n display: none;\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n &.in {\n display: block;\n }\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition(height .35s ease);\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot')\";\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')\";\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base solid;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: not-allowed;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 1px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n max-height: @navbar-collapse-max-height;\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\n }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: not-allowed;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n &[href] {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\n }\n}\n\n// Hover state, but only for links\na.badge {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n > .pull-left {\n margin-right: 10px;\n }\n > .pull-right {\n margin-left: 10px;\n }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n\n // Align badges within list items\n > .badge {\n float: right;\n }\n > .badge + .badge {\n margin-right: 5px;\n }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @list-group-hover-bg;\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: 10px 15px;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table {\n margin-bottom: 0;\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n overflow: hidden; // crop contents when collapsed\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n + .panel-collapse .panel-body {\n border-top: 1px solid @panel-inner-border;\n }\n }\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: auto;\n overflow-y: scroll;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0)}\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: none;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n margin-top: 15px;\n padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n visibility: visible;\n font-size: @font-size-small;\n line-height: 1.4;\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n text-decoration: none;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n text-align: left; // Reset given new insertion method\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Overrides for proper insertion\n white-space: normal;\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 18px;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#browsers\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n"]} |
New file |
| | |
| | | /*! |
| | | * Bootstrap v3.1.1 (http://getbootstrap.com) |
| | | * Copyright 2011-2014 Twitter, Inc. |
| | | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
| | | */ |
| | | |
| | | /*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print{display:none!important}} |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | .factory('todoItems', function(jsonFilter){ |
| | | |
| | | function randomInt(min, max) { |
| | | return Math.floor(Math.random() * (max - min + 1)) + min; |
| | | } |
| | | |
| | | function randomInNextFortnight() { |
| | | |
| | | function nn(x) { |
| | | return x<10? "0" + x: "" + x; |
| | | } |
| | | var nextFortnight = Date.now() + randomInt(0, 14) * (24 * 60 * 60 * 1000); |
| | | var d = new Date(nextFortnight); |
| | | var atMidnight = ""+(1900+d.getYear())+"-"+nn(d.getMonth())+"-"+nn(d.getDay()); |
| | | return atMidnight; |
| | | } |
| | | |
| | | var todoItems = [ |
| | | { |
| | | description: 'Buy bread', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: 1.75, |
| | | notes: "Buy from Budgens\nor failing that from Tesco's" |
| | | }, |
| | | { |
| | | description: 'Buy milk', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: 0.75, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Buy stamps', |
| | | category: 'Domestic', |
| | | complete: true, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: 10.00, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Mow lawn', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Organize brown bag', |
| | | category: 'Professional', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Pick up laundry', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: 7.50, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Sharpen knives', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Stage Isis release', |
| | | category: 'Professional', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Submit conference session', |
| | | category: 'Professional', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Vacuum house', |
| | | category: 'Domestic', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Write blog post', |
| | | category: 'Professional', |
| | | complete: true, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | }, |
| | | { |
| | | description: 'Write to penpal', |
| | | category: 'Other', |
| | | complete: false, |
| | | dueBy: randomInNextFortnight(), |
| | | cost: null, |
| | | notes: null |
| | | } |
| | | ]; |
| | | |
| | | console.log(jsonFilter(todoItems)); |
| | | |
| | | return { |
| | | get: function(){ |
| | | return todoItems; |
| | | }, |
| | | find: function(index){ |
| | | return todoItems[index]; |
| | | }, |
| | | set: function(todoItem){ |
| | | todoItems.push(todoItem); |
| | | }, |
| | | destroy: function(index){ |
| | | todoItems.splice(index, 1); |
| | | } |
| | | }; |
| | | }) |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp', ['ngRoute', 'ngSanitize', 'mgcrea.ngStrap', 'ui.router', 'xeditable']) |
| | | |
| | | .run([ '$rootScope', '$state', '$stateParams', 'editableOptions', |
| | | function ($rootScope, $state, $stateParams, editableOptions) { |
| | | |
| | | // from angular-ui-router example |
| | | |
| | | // It's very handy to add references to $state and $stateParams to the $rootScope |
| | | // so that you can access them from any scope within your applications.For example, |
| | | // <li ui-sref-active="active }"> will set the <li> // to active whenever |
| | | // 'todoItems.list' or one of its decendents is active. |
| | | $rootScope.$state = $state; |
| | | $rootScope.$stateParams = $stateParams; |
| | | |
| | | |
| | | // http://vitalets.github.io/angular-xeditable/#getstarted |
| | | editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default' |
| | | }]) |
| | | |
| | | .controller('appCtl', function($scope, $location) { |
| | | |
| | | $scope.startSearch = function(){ |
| | | $location.path('/'); |
| | | }; |
| | | }); |
| | | |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | .config(function($stateProvider, $urlRouterProvider){ |
| | | |
| | | // Use $urlRouterProvider to configure any redirects (when) and invalid urls (otherwise). |
| | | $urlRouterProvider |
| | | |
| | | // The `when` method says if the url is ever the 1st param, then redirect to the 2nd param |
| | | // Here we are just setting up some convenience urls. |
| | | .when('/c?id', '/todoItems/:id') |
| | | |
| | | // If the url is ever invalid, e.g. '/asdf', then redirect to '/' aka the home state |
| | | .otherwise('/'); |
| | | |
| | | $stateProvider |
| | | .state('list', { |
| | | url: "/", |
| | | templateUrl: 'assets/partials/list.html', |
| | | controller: 'indexCtl' |
| | | }) |
| | | .state('create', { |
| | | url: "/create", |
| | | templateUrl: 'assets/partials/create.html', |
| | | controller: 'addCtl' |
| | | }) |
| | | .state('edit', { |
| | | url: "/todoItems/:id", |
| | | templateUrl: 'assets/partials/edit.html', |
| | | controller: 'todoItemCtl' |
| | | }) |
| | | ; |
| | | }) |
| | | |
| | | .controller('indexCtl', function($scope, todoItems, $alert) { |
| | | |
| | | var alert = $alert({ |
| | | //title: 'Success!', |
| | | content: 'The todo item was deleted successfully.', |
| | | type: 'success', |
| | | container: '#alertContainer', |
| | | show: false, |
| | | duration: 3, |
| | | animation: "am-flip-x" |
| | | }); |
| | | |
| | | $scope.todoItems = todoItems.get(); |
| | | |
| | | $scope.delete = function(index){ |
| | | todoItems.destroy(index); |
| | | alert.show(); |
| | | }; |
| | | }) |
| | | |
| | | .controller('todoItemCtl', function ($scope, $stateParams, todoItems, focus) { |
| | | $scope.todoItem = todoItems.find($stateParams.id); |
| | | |
| | | focus('focusMe'); |
| | | }) |
| | | |
| | | .controller('addCtl', function ($scope, todoItems, $alert, focus) { |
| | | |
| | | var alert = $alert({ |
| | | //title: 'Success!', |
| | | content: 'The todo item was added successfully.', |
| | | type: 'success', |
| | | container: '#alertContainer', |
| | | show: false, |
| | | duration: 3, |
| | | animation: "am-flip-x" |
| | | }); |
| | | |
| | | focus('focusMe'); |
| | | |
| | | $scope.submit = function(){ |
| | | todoItems.set($scope.todoItem); |
| | | $scope.todoItem = null; |
| | | alert.show(); |
| | | }; |
| | | |
| | | }) |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | .directive('editable', function(){ |
| | | return { |
| | | restrict: 'AE', |
| | | templateUrl: '/assets/partials/editable.html', |
| | | scope: { |
| | | value: '=editable', |
| | | field: '@fieldType' |
| | | }, |
| | | controller: function($scope){ |
| | | |
| | | // create a new model to edit, and something for ng-show/ng-hide to watch |
| | | $scope.editor = { |
| | | showing: false, |
| | | value: $scope.value |
| | | }; |
| | | |
| | | $scope.toggleEditor = function(){ |
| | | $scope.editor.showing = !$scope.editor.showing; |
| | | }; |
| | | |
| | | $scope.field = ($scope.field) ? $scope.field : 'text'; |
| | | |
| | | $scope.save = function(){ |
| | | $scope.value = $scope.editor.value; |
| | | $scope.toggleEditor(); |
| | | }; |
| | | } |
| | | |
| | | |
| | | }; |
| | | }) |
| | | |
| | | |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | .filter('truncate', function(){ |
| | | return function(input, limit){ |
| | | return (input.length > limit) ? input.substr(0, limit)+'…' : input; |
| | | }; |
| | | }) |
| | | |
| | | .filter('paragraph', function(){ |
| | | return function(input){ |
| | | return input.replace(/\n/g, '<br />'); |
| | | }; |
| | | }) |
| | | |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | // see http://stackoverflow.com/questions/14833326/how-to-set-focus-in-angularjs |
| | | .directive('focusOn', function() { |
| | | return function(scope, elem, attr) { |
| | | scope.$on('focusOn', function(e, name) { |
| | | if(name === attr.focusOn) { |
| | | elem[0].focus(); |
| | | } |
| | | }); |
| | | }; |
| | | }) |
| | | |
| | | .factory('focus', function ($rootScope, $timeout) { |
| | | return function(name) { |
| | | $timeout(function (){ |
| | | $rootScope.$broadcast('focusOn', name); |
| | | }); |
| | | } |
| | | }) |
| | | ; |
New file |
| | |
| | | angular.module('todoItemsApp') |
| | | |
| | | .directive('gravatar', function(){ |
| | | return { |
| | | restrict: 'AE', |
| | | template: '<img src="{{img}}" class="{{class}}">', |
| | | replace: true, |
| | | link: function(scope, elem, attrs){ |
| | | var size = (attrs.size) ? attrs.size : 64; |
| | | scope.img = 'http://gravatar.com/avatar/'+md5(attrs.email)+'?s='+size; |
| | | scope.class = attrs.class; |
| | | } |
| | | } |
| | | }) |
| | | ; |
New file |
| | |
| | | function md5cycle(x, k) { |
| | | var a = x[0], b = x[1], c = x[2], d = x[3]; |
| | | |
| | | a = ff(a, b, c, d, k[0], 7, -680876936); |
| | | d = ff(d, a, b, c, k[1], 12, -389564586); |
| | | c = ff(c, d, a, b, k[2], 17, 606105819); |
| | | b = ff(b, c, d, a, k[3], 22, -1044525330); |
| | | a = ff(a, b, c, d, k[4], 7, -176418897); |
| | | d = ff(d, a, b, c, k[5], 12, 1200080426); |
| | | c = ff(c, d, a, b, k[6], 17, -1473231341); |
| | | b = ff(b, c, d, a, k[7], 22, -45705983); |
| | | a = ff(a, b, c, d, k[8], 7, 1770035416); |
| | | d = ff(d, a, b, c, k[9], 12, -1958414417); |
| | | c = ff(c, d, a, b, k[10], 17, -42063); |
| | | b = ff(b, c, d, a, k[11], 22, -1990404162); |
| | | a = ff(a, b, c, d, k[12], 7, 1804603682); |
| | | d = ff(d, a, b, c, k[13], 12, -40341101); |
| | | c = ff(c, d, a, b, k[14], 17, -1502002290); |
| | | b = ff(b, c, d, a, k[15], 22, 1236535329); |
| | | |
| | | a = gg(a, b, c, d, k[1], 5, -165796510); |
| | | d = gg(d, a, b, c, k[6], 9, -1069501632); |
| | | c = gg(c, d, a, b, k[11], 14, 643717713); |
| | | b = gg(b, c, d, a, k[0], 20, -373897302); |
| | | a = gg(a, b, c, d, k[5], 5, -701558691); |
| | | d = gg(d, a, b, c, k[10], 9, 38016083); |
| | | c = gg(c, d, a, b, k[15], 14, -660478335); |
| | | b = gg(b, c, d, a, k[4], 20, -405537848); |
| | | a = gg(a, b, c, d, k[9], 5, 568446438); |
| | | d = gg(d, a, b, c, k[14], 9, -1019803690); |
| | | c = gg(c, d, a, b, k[3], 14, -187363961); |
| | | b = gg(b, c, d, a, k[8], 20, 1163531501); |
| | | a = gg(a, b, c, d, k[13], 5, -1444681467); |
| | | d = gg(d, a, b, c, k[2], 9, -51403784); |
| | | c = gg(c, d, a, b, k[7], 14, 1735328473); |
| | | b = gg(b, c, d, a, k[12], 20, -1926607734); |
| | | |
| | | a = hh(a, b, c, d, k[5], 4, -378558); |
| | | d = hh(d, a, b, c, k[8], 11, -2022574463); |
| | | c = hh(c, d, a, b, k[11], 16, 1839030562); |
| | | b = hh(b, c, d, a, k[14], 23, -35309556); |
| | | a = hh(a, b, c, d, k[1], 4, -1530992060); |
| | | d = hh(d, a, b, c, k[4], 11, 1272893353); |
| | | c = hh(c, d, a, b, k[7], 16, -155497632); |
| | | b = hh(b, c, d, a, k[10], 23, -1094730640); |
| | | a = hh(a, b, c, d, k[13], 4, 681279174); |
| | | d = hh(d, a, b, c, k[0], 11, -358537222); |
| | | c = hh(c, d, a, b, k[3], 16, -722521979); |
| | | b = hh(b, c, d, a, k[6], 23, 76029189); |
| | | a = hh(a, b, c, d, k[9], 4, -640364487); |
| | | d = hh(d, a, b, c, k[12], 11, -421815835); |
| | | c = hh(c, d, a, b, k[15], 16, 530742520); |
| | | b = hh(b, c, d, a, k[2], 23, -995338651); |
| | | |
| | | a = ii(a, b, c, d, k[0], 6, -198630844); |
| | | d = ii(d, a, b, c, k[7], 10, 1126891415); |
| | | c = ii(c, d, a, b, k[14], 15, -1416354905); |
| | | b = ii(b, c, d, a, k[5], 21, -57434055); |
| | | a = ii(a, b, c, d, k[12], 6, 1700485571); |
| | | d = ii(d, a, b, c, k[3], 10, -1894986606); |
| | | c = ii(c, d, a, b, k[10], 15, -1051523); |
| | | b = ii(b, c, d, a, k[1], 21, -2054922799); |
| | | a = ii(a, b, c, d, k[8], 6, 1873313359); |
| | | d = ii(d, a, b, c, k[15], 10, -30611744); |
| | | c = ii(c, d, a, b, k[6], 15, -1560198380); |
| | | b = ii(b, c, d, a, k[13], 21, 1309151649); |
| | | a = ii(a, b, c, d, k[4], 6, -145523070); |
| | | d = ii(d, a, b, c, k[11], 10, -1120210379); |
| | | c = ii(c, d, a, b, k[2], 15, 718787259); |
| | | b = ii(b, c, d, a, k[9], 21, -343485551); |
| | | |
| | | x[0] = add32(a, x[0]); |
| | | x[1] = add32(b, x[1]); |
| | | x[2] = add32(c, x[2]); |
| | | x[3] = add32(d, x[3]); |
| | | |
| | | } |
| | | |
| | | function cmn(q, a, b, x, s, t) { |
| | | a = add32(add32(a, q), add32(x, t)); |
| | | return add32((a << s) | (a >>> (32 - s)), b); |
| | | } |
| | | |
| | | function ff(a, b, c, d, x, s, t) { |
| | | return cmn((b & c) | ((~b) & d), a, b, x, s, t); |
| | | } |
| | | |
| | | function gg(a, b, c, d, x, s, t) { |
| | | return cmn((b & d) | (c & (~d)), a, b, x, s, t); |
| | | } |
| | | |
| | | function hh(a, b, c, d, x, s, t) { |
| | | return cmn(b ^ c ^ d, a, b, x, s, t); |
| | | } |
| | | |
| | | function ii(a, b, c, d, x, s, t) { |
| | | return cmn(c ^ (b | (~d)), a, b, x, s, t); |
| | | } |
| | | |
| | | function md51(s) { |
| | | txt = ''; |
| | | var n = s.length, |
| | | state = [1732584193, -271733879, -1732584194, 271733878], i; |
| | | for (i=64; i<=s.length; i+=64) { |
| | | md5cycle(state, md5blk(s.substring(i-64, i))); |
| | | } |
| | | s = s.substring(i-64); |
| | | var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; |
| | | for (i=0; i<s.length; i++) |
| | | tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3); |
| | | tail[i>>2] |= 0x80 << ((i%4) << 3); |
| | | if (i > 55) { |
| | | md5cycle(state, tail); |
| | | for (i=0; i<16; i++) tail[i] = 0; |
| | | } |
| | | tail[14] = n*8; |
| | | md5cycle(state, tail); |
| | | return state; |
| | | } |
| | | |
| | | /* there needs to be support for Unicode here, |
| | | * unless we pretend that we can redefine the MD-5 |
| | | * algorithm for multi-byte characters (perhaps |
| | | * by adding every four 16-bit characters and |
| | | * shortening the sum to 32 bits). Otherwise |
| | | * I suggest performing MD-5 as if every character |
| | | * was two bytes--e.g., 0040 0025 = @%--but then |
| | | * how will an ordinary MD-5 sum be matched? |
| | | * There is no way to standardize text to something |
| | | * like UTF-8 before transformation; speed cost is |
| | | * utterly prohibitive. The JavaScript standard |
| | | * itself needs to look at this: it should start |
| | | * providing access to strings as preformed UTF-8 |
| | | * 8-bit unsigned value arrays. |
| | | */ |
| | | function md5blk(s) { /* I figured global was faster. */ |
| | | var md5blks = [], i; /* Andy King said do it this way. */ |
| | | for (i=0; i<64; i+=4) { |
| | | md5blks[i>>2] = s.charCodeAt(i) |
| | | + (s.charCodeAt(i+1) << 8) |
| | | + (s.charCodeAt(i+2) << 16) |
| | | + (s.charCodeAt(i+3) << 24); |
| | | } |
| | | return md5blks; |
| | | } |
| | | |
| | | var hex_chr = '0123456789abcdef'.split(''); |
| | | |
| | | function rhex(n) |
| | | { |
| | | var s='', j=0; |
| | | for(; j<4; j++) |
| | | s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] |
| | | + hex_chr[(n >> (j * 8)) & 0x0F]; |
| | | return s; |
| | | } |
| | | |
| | | function hex(x) { |
| | | for (var i=0; i<x.length; i++) |
| | | x[i] = rhex(x[i]); |
| | | return x.join(''); |
| | | } |
| | | |
| | | function md5(s) { |
| | | return hex(md51(s)); |
| | | } |
| | | |
| | | /* this function is much faster, |
| | | so if possible we use it. Some IEs |
| | | are the only ones I know of that |
| | | need the idiotic second function, |
| | | generated by an if clause. */ |
| | | |
| | | function add32(a, b) { |
| | | return (a + b) & 0xFFFFFFFF; |
| | | } |
| | | |
| | | if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') { |
| | | function add32(x, y) { |
| | | var lsw = (x & 0xFFFF) + (y & 0xFFFF), |
| | | msw = (x >> 16) + (y >> 16) + (lsw >> 16); |
| | | return (msw << 16) | (lsw & 0xFFFF); |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | (function(window, document, undefined) { |
| | | 'use strict'; |
| | | // Source: module.js |
| | | angular.module('mgcrea.ngStrap', [ |
| | | 'mgcrea.ngStrap.modal', |
| | | 'mgcrea.ngStrap.aside', |
| | | 'mgcrea.ngStrap.alert', |
| | | 'mgcrea.ngStrap.button', |
| | | 'mgcrea.ngStrap.select', |
| | | 'mgcrea.ngStrap.datepicker', |
| | | 'mgcrea.ngStrap.timepicker', |
| | | 'mgcrea.ngStrap.navbar', |
| | | 'mgcrea.ngStrap.tooltip', |
| | | 'mgcrea.ngStrap.popover', |
| | | 'mgcrea.ngStrap.dropdown', |
| | | 'mgcrea.ngStrap.typeahead', |
| | | 'mgcrea.ngStrap.scrollspy', |
| | | 'mgcrea.ngStrap.affix', |
| | | 'mgcrea.ngStrap.tab' |
| | | ]); |
| | | |
| | | // Source: affix.js |
| | | angular.module('mgcrea.ngStrap.affix', [ |
| | | 'mgcrea.ngStrap.helpers.dimensions', |
| | | 'mgcrea.ngStrap.helpers.debounce' |
| | | ]).provider('$affix', function () { |
| | | var defaults = this.defaults = { offsetTop: 'auto' }; |
| | | this.$get = [ |
| | | '$window', |
| | | 'debounce', |
| | | 'dimensions', |
| | | function ($window, debounce, dimensions) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var windowEl = angular.element($window); |
| | | function AffixFactory(element, config) { |
| | | var $affix = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var targetEl = options.target; |
| | | // Initial private vars |
| | | var reset = 'affix affix-top affix-bottom', initialAffixTop = 0, initialOffsetTop = 0, offsetTop = 0, offsetBottom = 0, affixed = null, unpin = null; |
| | | var parent = element.parent(); |
| | | // Options: custom parent |
| | | if (options.offsetParent) { |
| | | if (options.offsetParent.match(/^\d+$/)) { |
| | | for (var i = 0; i < options.offsetParent * 1 - 1; i++) { |
| | | parent = parent.parent(); |
| | | } |
| | | } else { |
| | | parent = angular.element(options.offsetParent); |
| | | } |
| | | } |
| | | $affix.init = function () { |
| | | $affix.$parseOffsets(); |
| | | initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop; |
| | | // Bind events |
| | | targetEl.on('scroll', $affix.checkPosition); |
| | | targetEl.on('click', $affix.checkPositionWithEventLoop); |
| | | windowEl.on('resize', $affix.$debouncedOnResize); |
| | | // Both of these checkPosition() calls are necessary for the case where |
| | | // the user hits refresh after scrolling to the bottom of the page. |
| | | $affix.checkPosition(); |
| | | $affix.checkPositionWithEventLoop(); |
| | | }; |
| | | $affix.destroy = function () { |
| | | // Unbind events |
| | | targetEl.off('scroll', $affix.checkPosition); |
| | | targetEl.off('click', $affix.checkPositionWithEventLoop); |
| | | windowEl.off('resize', $affix.$debouncedOnResize); |
| | | }; |
| | | $affix.checkPositionWithEventLoop = function () { |
| | | setTimeout($affix.checkPosition, 1); |
| | | }; |
| | | $affix.checkPosition = function () { |
| | | // if (!this.$element.is(':visible')) return |
| | | var scrollTop = getScrollTop(); |
| | | var position = dimensions.offset(element[0]); |
| | | var elementHeight = dimensions.height(element[0]); |
| | | // Get required affix class according to position |
| | | var affix = getRequiredAffixClass(unpin, position, elementHeight); |
| | | // Did affix status changed this last check? |
| | | if (affixed === affix) |
| | | return; |
| | | affixed = affix; |
| | | // Add proper affix class |
| | | element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : '')); |
| | | if (affix === 'top') { |
| | | unpin = null; |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | element.css('top', ''); |
| | | } else if (affix === 'bottom') { |
| | | if (options.offsetUnpin) { |
| | | unpin = -(options.offsetUnpin * 1); |
| | | } else { |
| | | // Calculate unpin threshold when affixed to bottom. |
| | | // Hopefully the browser scrolls pixel by pixel. |
| | | unpin = position.top - scrollTop; |
| | | } |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px'); |
| | | } else { |
| | | // affix === 'middle' |
| | | unpin = null; |
| | | element.css('position', 'fixed'); |
| | | element.css('top', initialAffixTop + 'px'); |
| | | } |
| | | }; |
| | | $affix.$onResize = function () { |
| | | $affix.$parseOffsets(); |
| | | $affix.checkPosition(); |
| | | }; |
| | | $affix.$debouncedOnResize = debounce($affix.$onResize, 50); |
| | | $affix.$parseOffsets = function () { |
| | | // Reset position to calculate correct offsetTop |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | if (options.offsetTop) { |
| | | if (options.offsetTop === 'auto') { |
| | | options.offsetTop = '+0'; |
| | | } |
| | | if (options.offsetTop.match(/^[-+]\d+$/)) { |
| | | initialAffixTop = -options.offsetTop * 1; |
| | | if (options.offsetParent) { |
| | | offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1; |
| | | } else { |
| | | offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1; |
| | | } |
| | | } else { |
| | | offsetTop = options.offsetTop * 1; |
| | | } |
| | | } |
| | | if (options.offsetBottom) { |
| | | if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) { |
| | | // add 1 pixel due to rounding problems... |
| | | offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1; |
| | | } else { |
| | | offsetBottom = options.offsetBottom * 1; |
| | | } |
| | | } |
| | | }; |
| | | // Private methods |
| | | function getRequiredAffixClass(unpin, position, elementHeight) { |
| | | var scrollTop = getScrollTop(); |
| | | var scrollHeight = getScrollHeight(); |
| | | if (scrollTop <= offsetTop) { |
| | | return 'top'; |
| | | } else if (unpin !== null && scrollTop + unpin <= position.top) { |
| | | return 'middle'; |
| | | } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) { |
| | | return 'bottom'; |
| | | } else { |
| | | return 'middle'; |
| | | } |
| | | } |
| | | function getScrollTop() { |
| | | return targetEl[0] === $window ? $window.pageYOffset : targetEl[0] === $window; |
| | | } |
| | | function getScrollHeight() { |
| | | return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight; |
| | | } |
| | | $affix.init(); |
| | | return $affix; |
| | | } |
| | | return AffixFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAffix', [ |
| | | '$affix', |
| | | '$window', |
| | | function ($affix, $window) { |
| | | return { |
| | | restrict: 'EAC', |
| | | require: '^?bsAffixTarget', |
| | | link: function postLink(scope, element, attr, affixTarget) { |
| | | var options = { |
| | | scope: scope, |
| | | offsetTop: 'auto', |
| | | target: affixTarget ? affixTarget.$element : angular.element($window) |
| | | }; |
| | | angular.forEach([ |
| | | 'offsetTop', |
| | | 'offsetBottom', |
| | | 'offsetParent', |
| | | 'offsetUnpin' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | var affix = $affix(element, options); |
| | | scope.$on('$destroy', function () { |
| | | options = null; |
| | | affix = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsAffixTarget', function () { |
| | | return { |
| | | controller: [ |
| | | '$element', |
| | | function ($element) { |
| | | this.$element = $element; |
| | | } |
| | | ] |
| | | }; |
| | | }); |
| | | |
| | | // Source: alert.js |
| | | // @BUG: following snippet won't compile correctly |
| | | // @TODO: submit issue to core |
| | | // '<span ng-if="title"><strong ng-bind="title"></strong> </span><span ng-bind-html="content"></span>' + |
| | | angular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal']).provider('$alert', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'alert', |
| | | placement: null, |
| | | template: 'alert/alert.tpl.html', |
| | | container: false, |
| | | element: null, |
| | | backdrop: false, |
| | | keyboard: true, |
| | | show: true, |
| | | duration: false, |
| | | type: false, |
| | | dismissable: true |
| | | }; |
| | | this.$get = [ |
| | | '$modal', |
| | | '$timeout', |
| | | function ($modal, $timeout) { |
| | | function AlertFactory(config) { |
| | | var $alert = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $alert = $modal(options); |
| | | // Support scope as string options [/*title, content, */ type, dismissable] |
| | | $alert.$scope.dismissable = !!options.dismissable; |
| | | if (options.type) { |
| | | $alert.$scope.type = options.type; |
| | | } |
| | | // Support auto-close duration |
| | | var show = $alert.show; |
| | | if (options.duration) { |
| | | $alert.show = function () { |
| | | show(); |
| | | $timeout(function () { |
| | | $alert.hide(); |
| | | }, options.duration * 1000); |
| | | }; |
| | | } |
| | | return $alert; |
| | | } |
| | | return AlertFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAlert', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$alert', |
| | | function ($window, $location, $sce, $alert) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'placement', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation', |
| | | 'duration', |
| | | 'dismissable' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content', |
| | | 'type' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsAlert && scope.$watch(attr.bsAlert, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize alert |
| | | var alert = $alert(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', alert.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | alert.destroy(); |
| | | options = null; |
| | | alert = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: button.js |
| | | angular.module('mgcrea.ngStrap.button', []).provider('$button', function () { |
| | | var defaults = this.defaults = { |
| | | activeClass: 'active', |
| | | toggleEvent: 'click' |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsCheckboxGroup', function () { |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | compile: function postLink(element, attr) { |
| | | element.attr('data-toggle', 'buttons'); |
| | | element.removeAttr('ng-model'); |
| | | var children = element[0].querySelectorAll('input[type="checkbox"]'); |
| | | angular.forEach(children, function (child) { |
| | | var childEl = angular.element(child); |
| | | childEl.attr('bs-checkbox', ''); |
| | | childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value')); |
| | | }); |
| | | } |
| | | }; |
| | | }).directive('bsCheckbox', [ |
| | | '$button', |
| | | '$$rAF', |
| | | function ($button, $$rAF) { |
| | | var defaults = $button.defaults; |
| | | var constantValueRegExp = /^(true|false|\d+)$/; |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | var options = defaults; |
| | | // Support label > input[type="checkbox"] |
| | | var isInput = element[0].nodeName === 'INPUT'; |
| | | var activeElement = isInput ? element.parent() : element; |
| | | var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true; |
| | | if (constantValueRegExp.test(attr.trueValue)) { |
| | | trueValue = scope.$eval(attr.trueValue); |
| | | } |
| | | var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false; |
| | | if (constantValueRegExp.test(attr.falseValue)) { |
| | | falseValue = scope.$eval(attr.falseValue); |
| | | } |
| | | // Parse exotic values |
| | | var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean'; |
| | | if (hasExoticValues) { |
| | | controller.$parsers.push(function (viewValue) { |
| | | // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue); |
| | | return viewValue ? trueValue : falseValue; |
| | | }); |
| | | // Fix rendering for exotic values |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | controller.$render(); |
| | | }); |
| | | } |
| | | // model -> view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var isActive = angular.equals(controller.$modelValue, trueValue); |
| | | $$rAF(function () { |
| | | if (isInput) |
| | | element[0].checked = isActive; |
| | | activeElement.toggleClass(options.activeClass, isActive); |
| | | }); |
| | | }; |
| | | // view -> model |
| | | element.bind(options.toggleEvent, function () { |
| | | scope.$apply(function () { |
| | | // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue); |
| | | if (!isInput) { |
| | | controller.$setViewValue(!activeElement.hasClass('active')); |
| | | } |
| | | if (!hasExoticValues) { |
| | | controller.$render(); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsRadioGroup', function () { |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | compile: function postLink(element, attr) { |
| | | element.attr('data-toggle', 'buttons'); |
| | | element.removeAttr('ng-model'); |
| | | var children = element[0].querySelectorAll('input[type="radio"]'); |
| | | angular.forEach(children, function (child) { |
| | | angular.element(child).attr('bs-radio', ''); |
| | | angular.element(child).attr('ng-model', attr.ngModel); |
| | | }); |
| | | } |
| | | }; |
| | | }).directive('bsRadio', [ |
| | | '$button', |
| | | '$$rAF', |
| | | function ($button, $$rAF) { |
| | | var defaults = $button.defaults; |
| | | var constantValueRegExp = /^(true|false|\d+)$/; |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | var options = defaults; |
| | | // Support `label > input[type="radio"]` markup |
| | | var isInput = element[0].nodeName === 'INPUT'; |
| | | var activeElement = isInput ? element.parent() : element; |
| | | var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value; |
| | | // model -> view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var isActive = angular.equals(controller.$modelValue, value); |
| | | $$rAF(function () { |
| | | if (isInput) |
| | | element[0].checked = isActive; |
| | | activeElement.toggleClass(options.activeClass, isActive); |
| | | }); |
| | | }; |
| | | // view -> model |
| | | element.bind(options.toggleEvent, function () { |
| | | scope.$apply(function () { |
| | | // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue); |
| | | controller.$setViewValue(value); |
| | | controller.$render(); |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: aside.js |
| | | angular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal']).provider('$aside', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade-and-slide-right', |
| | | prefixClass: 'aside', |
| | | placement: 'right', |
| | | template: 'aside/aside.tpl.html', |
| | | contentTemplate: false, |
| | | container: false, |
| | | element: null, |
| | | backdrop: true, |
| | | keyboard: true, |
| | | html: false, |
| | | show: true |
| | | }; |
| | | this.$get = [ |
| | | '$modal', |
| | | function ($modal) { |
| | | function AsideFactory(config) { |
| | | var $aside = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $aside = $modal(options); |
| | | return $aside; |
| | | } |
| | | return AsideFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAside', [ |
| | | '$window', |
| | | '$sce', |
| | | '$aside', |
| | | function ($window, $sce, $aside) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'backdrop', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsAside && scope.$watch(attr.bsAside, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize aside |
| | | var aside = $aside(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', aside.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | aside.destroy(); |
| | | options = null; |
| | | aside = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: datepicker.js |
| | | angular.module('mgcrea.ngStrap.datepicker', [ |
| | | 'mgcrea.ngStrap.helpers.dateParser', |
| | | 'mgcrea.ngStrap.tooltip' |
| | | ]).provider('$datepicker', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'datepicker', |
| | | placement: 'bottom-left', |
| | | template: 'datepicker/datepicker.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | useNative: false, |
| | | dateType: 'date', |
| | | dateFormat: 'shortDate', |
| | | modelDateFormat: null, |
| | | dayFormat: 'dd', |
| | | strictFormat: false, |
| | | autoclose: false, |
| | | minDate: -Infinity, |
| | | maxDate: +Infinity, |
| | | startView: 0, |
| | | minView: 0, |
| | | startWeek: 0, |
| | | iconLeft: 'glyphicon glyphicon-chevron-left', |
| | | iconRight: 'glyphicon glyphicon-chevron-right' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$sce', |
| | | '$locale', |
| | | 'dateFilter', |
| | | 'datepickerViews', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $sce, $locale, dateFilter, datepickerViews, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | if (!defaults.lang) |
| | | defaults.lang = $locale.id; |
| | | function DatepickerFactory(element, controller, config) { |
| | | var $datepicker = $tooltip(element, angular.extend({}, defaults, config)); |
| | | var parentScope = config.scope; |
| | | var options = $datepicker.$options; |
| | | var scope = $datepicker.$scope; |
| | | if (options.startView) |
| | | options.startView -= options.minView; |
| | | // View vars |
| | | var pickerViews = datepickerViews($datepicker); |
| | | $datepicker.$views = pickerViews.views; |
| | | var viewDate = pickerViews.viewDate; |
| | | scope.$mode = options.startView; |
| | | scope.$iconLeft = options.iconLeft; |
| | | scope.$iconRight = options.iconRight; |
| | | var $picker = $datepicker.$views[scope.$mode]; |
| | | // Scope methods |
| | | scope.$select = function (date) { |
| | | $datepicker.select(date); |
| | | }; |
| | | scope.$selectPane = function (value) { |
| | | $datepicker.$selectPane(value); |
| | | }; |
| | | scope.$toggleMode = function () { |
| | | $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length); |
| | | }; |
| | | // Public methods |
| | | $datepicker.update = function (date) { |
| | | // console.warn('$datepicker.update() newValue=%o', date); |
| | | if (angular.isDate(date) && !isNaN(date.getTime())) { |
| | | $datepicker.$date = date; |
| | | $picker.update.call($picker, date); |
| | | } |
| | | // Build only if pristine |
| | | $datepicker.$build(true); |
| | | }; |
| | | $datepicker.select = function (date, keep) { |
| | | // console.warn('$datepicker.select', date, scope.$mode); |
| | | if (!angular.isDate(controller.$dateValue)) |
| | | controller.$dateValue = new Date(date); |
| | | controller.$dateValue.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); |
| | | if (!scope.$mode || keep) { |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | if (options.autoclose && !keep) { |
| | | $datepicker.hide(true); |
| | | } |
| | | } else { |
| | | angular.extend(viewDate, { |
| | | year: date.getFullYear(), |
| | | month: date.getMonth(), |
| | | date: date.getDate() |
| | | }); |
| | | $datepicker.setMode(scope.$mode - 1); |
| | | $datepicker.$build(); |
| | | } |
| | | }; |
| | | $datepicker.setMode = function (mode) { |
| | | // console.warn('$datepicker.setMode', mode); |
| | | scope.$mode = mode; |
| | | $picker = $datepicker.$views[scope.$mode]; |
| | | $datepicker.$build(); |
| | | }; |
| | | // Protected methods |
| | | $datepicker.$build = function (pristine) { |
| | | // console.warn('$datepicker.$build() viewDate=%o', viewDate); |
| | | if (pristine === true && $picker.built) |
| | | return; |
| | | if (pristine === false && !$picker.built) |
| | | return; |
| | | $picker.build.call($picker); |
| | | }; |
| | | $datepicker.$updateSelected = function () { |
| | | for (var i = 0, l = scope.rows.length; i < l; i++) { |
| | | angular.forEach(scope.rows[i], updateSelected); |
| | | } |
| | | }; |
| | | $datepicker.$isSelected = function (date) { |
| | | return $picker.isSelected(date); |
| | | }; |
| | | $datepicker.$selectPane = function (value) { |
| | | var steps = $picker.steps; |
| | | var targetDate = new Date(Date.UTC(viewDate.year + (steps.year || 0) * value, viewDate.month + (steps.month || 0) * value, viewDate.date + (steps.day || 0) * value)); |
| | | angular.extend(viewDate, { |
| | | year: targetDate.getUTCFullYear(), |
| | | month: targetDate.getUTCMonth(), |
| | | date: targetDate.getUTCDate() |
| | | }); |
| | | $datepicker.$build(); |
| | | }; |
| | | $datepicker.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | if (targetEl[0].nodeName.toLowerCase() !== 'button') { |
| | | targetEl = targetEl.parent(); |
| | | } |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $datepicker.$onKeyDown = function (evt) { |
| | | if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | if (evt.keyCode === 13) { |
| | | if (!scope.$mode) { |
| | | return $datepicker.hide(true); |
| | | } else { |
| | | return scope.$apply(function () { |
| | | $datepicker.setMode(scope.$mode - 1); |
| | | }); |
| | | } |
| | | } |
| | | // Navigate with keyboard |
| | | $picker.onKeyDown(evt); |
| | | parentScope.$digest(); |
| | | }; |
| | | // Private |
| | | function updateSelected(el) { |
| | | el.selected = $datepicker.$isSelected(el.date); |
| | | } |
| | | function focusElement() { |
| | | element[0].focus(); |
| | | } |
| | | // Overrides |
| | | var _init = $datepicker.init; |
| | | $datepicker.init = function () { |
| | | if (isNative && options.useNative) { |
| | | element.prop('type', 'date'); |
| | | element.css('-webkit-appearance', 'textfield'); |
| | | return; |
| | | } else if (isTouch) { |
| | | element.prop('type', 'text'); |
| | | element.attr('readonly', 'true'); |
| | | element.on('click', focusElement); |
| | | } |
| | | _init(); |
| | | }; |
| | | var _destroy = $datepicker.destroy; |
| | | $datepicker.destroy = function () { |
| | | if (isNative && options.useNative) { |
| | | element.off('click', focusElement); |
| | | } |
| | | _destroy(); |
| | | }; |
| | | var _show = $datepicker.show; |
| | | $datepicker.show = function () { |
| | | _show(); |
| | | setTimeout(function () { |
| | | $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $datepicker.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $datepicker.hide; |
| | | $datepicker.hide = function (blur) { |
| | | $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $datepicker.$onKeyDown); |
| | | } |
| | | _hide(blur); |
| | | }; |
| | | return $datepicker; |
| | | } |
| | | DatepickerFactory.defaults = defaults; |
| | | return DatepickerFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsDatepicker', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$datepicker', |
| | | '$dateParser', |
| | | '$timeout', |
| | | function ($window, $parse, $q, $locale, dateFilter, $datepicker, $dateParser, $timeout) { |
| | | var defaults = $datepicker.defaults; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | var isNumeric = function (n) { |
| | | return !isNaN(parseFloat(n)) && isFinite(n); |
| | | }; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | controller: controller |
| | | }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'autoclose', |
| | | 'dateType', |
| | | 'dateFormat', |
| | | 'modelDateFormat', |
| | | 'dayFormat', |
| | | 'strictFormat', |
| | | 'startWeek', |
| | | 'useNative', |
| | | 'lang', |
| | | 'startView', |
| | | 'minView' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Initialize datepicker |
| | | if (isNative && options.useNative) |
| | | options.dateFormat = 'yyyy-MM-dd'; |
| | | var datepicker = $datepicker(element, controller, options); |
| | | options = datepicker.$options; |
| | | // Observe attributes for changes |
| | | angular.forEach([ |
| | | 'minDate', |
| | | 'maxDate' |
| | | ], function (key) { |
| | | // console.warn('attr.$observe(%s)', key, attr[key]); |
| | | angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) { |
| | | // console.warn('attr.$observe(%s)=%o', key, newValue); |
| | | if (newValue === 'today') { |
| | | var today = new Date(); |
| | | datepicker.$options[key] = +new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, key === 'minDate' ? 0 : -1); |
| | | } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) { |
| | | // Support {{ dateObj }} |
| | | datepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2)); |
| | | } else if (isNumeric(newValue)) { |
| | | datepicker.$options[key] = +new Date(parseInt(newValue, 10)); |
| | | } else { |
| | | datepicker.$options[key] = +new Date(newValue); |
| | | } |
| | | // Build only if dirty |
| | | !isNaN(datepicker.$options[key]) && datepicker.$build(false); |
| | | }); |
| | | }); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | datepicker.update(controller.$dateValue); |
| | | }, true); |
| | | var dateParser = $dateParser({ |
| | | format: options.dateFormat, |
| | | lang: options.lang, |
| | | strict: options.strictFormat |
| | | }); |
| | | // viewValue -> $parsers -> modelValue |
| | | controller.$parsers.unshift(function (viewValue) { |
| | | // console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue); |
| | | // Null values should correctly reset the model value & validity |
| | | if (!viewValue) { |
| | | controller.$setValidity('date', true); |
| | | return; |
| | | } |
| | | var parsedDate = dateParser.parse(viewValue, controller.$dateValue); |
| | | if (!parsedDate || isNaN(parsedDate.getTime())) { |
| | | controller.$setValidity('date', false); |
| | | return; |
| | | } else { |
| | | var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate; |
| | | var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate; |
| | | var isValid = isMinValid && isMaxValid; |
| | | controller.$setValidity('date', isValid); |
| | | controller.$setValidity('min', isMinValid); |
| | | controller.$setValidity('max', isMaxValid); |
| | | // Only update the model when we have a valid date |
| | | if (isValid) |
| | | controller.$dateValue = parsedDate; |
| | | } |
| | | if (options.dateType === 'string') { |
| | | return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat); |
| | | } else if (options.dateType === 'number') { |
| | | return controller.$dateValue.getTime(); |
| | | } else if (options.dateType === 'iso') { |
| | | return controller.$dateValue.toISOString(); |
| | | } else { |
| | | return new Date(controller.$dateValue); |
| | | } |
| | | }); |
| | | // modelValue -> $formatters -> viewValue |
| | | controller.$formatters.push(function (modelValue) { |
| | | // console.warn('$formatter("%s"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue); |
| | | var date; |
| | | if (angular.isUndefined(modelValue) || modelValue === null) { |
| | | date = NaN; |
| | | } else if (angular.isDate(modelValue)) { |
| | | date = modelValue; |
| | | } else if (options.dateType === 'string') { |
| | | date = dateParser.parse(modelValue, null, options.modelDateFormat); |
| | | } else { |
| | | date = new Date(modelValue); |
| | | } |
| | | // Setup default value? |
| | | // if(isNaN(date.getTime())) { |
| | | // var today = new Date(); |
| | | // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0); |
| | | // } |
| | | controller.$dateValue = date; |
| | | return controller.$dateValue; |
| | | }); |
| | | // viewValue -> element |
| | | controller.$render = function () { |
| | | // console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue); |
| | | element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.dateFormat)); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | datepicker.destroy(); |
| | | options = null; |
| | | datepicker = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).provider('datepickerViews', function () { |
| | | var defaults = this.defaults = { |
| | | dayFormat: 'dd', |
| | | daySplit: 7 |
| | | }; |
| | | // Split array into smaller arrays |
| | | function split(arr, size) { |
| | | var arrays = []; |
| | | while (arr.length > 0) { |
| | | arrays.push(arr.splice(0, size)); |
| | | } |
| | | return arrays; |
| | | } |
| | | // Modulus operator |
| | | function mod(n, m) { |
| | | return (n % m + m) % m; |
| | | } |
| | | this.$get = [ |
| | | '$locale', |
| | | '$sce', |
| | | 'dateFilter', |
| | | function ($locale, $sce, dateFilter) { |
| | | return function (picker) { |
| | | var scope = picker.$scope; |
| | | var options = picker.$options; |
| | | var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY; |
| | | var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek)); |
| | | var weekDaysLabelsHtml = $sce.trustAsHtml('<th class="dow text-center">' + weekDaysLabels.join('</th><th class="dow text-center">') + '</th>'); |
| | | var startDate = picker.$date || new Date(); |
| | | var viewDate = { |
| | | year: startDate.getFullYear(), |
| | | month: startDate.getMonth(), |
| | | date: startDate.getDate() |
| | | }; |
| | | var timezoneOffset = startDate.getTimezoneOffset() * 60000; |
| | | var views = [ |
| | | { |
| | | format: options.dayFormat, |
| | | split: 7, |
| | | steps: { month: 1 }, |
| | | update: function (date, force) { |
| | | if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getDate() !== viewDate.date) { |
| | | viewDate.date = picker.$date.getDate(); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset(); |
| | | var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 86400000), firstDateOffset = firstDate.getTimezoneOffset(); |
| | | // Handle daylight time switch |
| | | if (firstDateOffset !== firstDayOfMonthOffset) |
| | | firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60000); |
| | | var days = [], day; |
| | | for (var i = 0; i < 42; i++) { |
| | | // < 7 * 6 |
| | | day = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i); |
| | | days.push({ |
| | | date: day, |
| | | label: dateFilter(day, this.format), |
| | | selected: picker.$date && this.isSelected(day), |
| | | muted: day.getMonth() !== viewDate.month, |
| | | disabled: this.isDisabled(day) |
| | | }); |
| | | } |
| | | scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy'); |
| | | scope.showLabels = true; |
| | | scope.labels = weekDaysLabelsHtml; |
| | | scope.rows = split(days, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | return date.getTime() < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualTime = picker.$date.getTime(); |
| | | var newDate; |
| | | if (evt.keyCode === 37) |
| | | newDate = new Date(actualTime - 1 * 86400000); |
| | | else if (evt.keyCode === 38) |
| | | newDate = new Date(actualTime - 7 * 86400000); |
| | | else if (evt.keyCode === 39) |
| | | newDate = new Date(actualTime + 1 * 86400000); |
| | | else if (evt.keyCode === 40) |
| | | newDate = new Date(actualTime + 7 * 86400000); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | }, |
| | | { |
| | | name: 'month', |
| | | format: 'MMM', |
| | | split: 4, |
| | | steps: { year: 1 }, |
| | | update: function (date, force) { |
| | | if (!this.built || date.getFullYear() !== viewDate.year) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getMonth() !== viewDate.month) { |
| | | angular.extend(viewDate, { |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstMonth = new Date(viewDate.year, 0, 1); |
| | | var months = [], month; |
| | | for (var i = 0; i < 12; i++) { |
| | | month = new Date(viewDate.year, i, 1); |
| | | months.push({ |
| | | date: month, |
| | | label: dateFilter(month, this.format), |
| | | selected: picker.$isSelected(month), |
| | | disabled: this.isDisabled(month) |
| | | }); |
| | | } |
| | | scope.title = dateFilter(month, 'yyyy'); |
| | | scope.showLabels = false; |
| | | scope.rows = split(months, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0); |
| | | return lastDate < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualMonth = picker.$date.getMonth(); |
| | | var newDate = new Date(picker.$date); |
| | | if (evt.keyCode === 37) |
| | | newDate.setMonth(actualMonth - 1); |
| | | else if (evt.keyCode === 38) |
| | | newDate.setMonth(actualMonth - 4); |
| | | else if (evt.keyCode === 39) |
| | | newDate.setMonth(actualMonth + 1); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setMonth(actualMonth + 4); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | }, |
| | | { |
| | | name: 'year', |
| | | format: 'yyyy', |
| | | split: 4, |
| | | steps: { year: 12 }, |
| | | update: function (date, force) { |
| | | if (!this.built || force || parseInt(date.getFullYear() / 20, 10) !== parseInt(viewDate.year / 20, 10)) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getFullYear() !== viewDate.year) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstYear = viewDate.year - viewDate.year % (this.split * 3); |
| | | var years = [], year; |
| | | for (var i = 0; i < 12; i++) { |
| | | year = new Date(firstYear + i, 0, 1); |
| | | years.push({ |
| | | date: year, |
| | | label: dateFilter(year, this.format), |
| | | selected: picker.$isSelected(year), |
| | | disabled: this.isDisabled(year) |
| | | }); |
| | | } |
| | | scope.title = years[0].label + '-' + years[years.length - 1].label; |
| | | scope.showLabels = false; |
| | | scope.rows = split(years, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | var lastDate = +new Date(date.getFullYear() + 1, 0, 0); |
| | | return lastDate < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualYear = picker.$date.getFullYear(), newDate = new Date(picker.$date); |
| | | if (evt.keyCode === 37) |
| | | newDate.setYear(actualYear - 1); |
| | | else if (evt.keyCode === 38) |
| | | newDate.setYear(actualYear - 4); |
| | | else if (evt.keyCode === 39) |
| | | newDate.setYear(actualYear + 1); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setYear(actualYear + 4); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | } |
| | | ]; |
| | | return { |
| | | views: options.minView ? Array.prototype.slice.call(views, options.minView) : views, |
| | | viewDate: viewDate |
| | | }; |
| | | }; |
| | | } |
| | | ]; |
| | | }); |
| | | |
| | | // Source: date-parser.js |
| | | angular.module('mgcrea.ngStrap.helpers.dateParser', []).provider('$dateParser', [ |
| | | '$localeProvider', |
| | | function ($localeProvider) { |
| | | var proto = Date.prototype; |
| | | function isNumeric(n) { |
| | | return !isNaN(parseFloat(n)) && isFinite(n); |
| | | } |
| | | var defaults = this.defaults = { |
| | | format: 'shortDate', |
| | | strict: false |
| | | }; |
| | | this.$get = [ |
| | | '$locale', |
| | | function ($locale) { |
| | | var DateParserFactory = function (config) { |
| | | var options = angular.extend({}, defaults, config); |
| | | var $dateParser = {}; |
| | | var regExpMap = { |
| | | 'sss': '[0-9]{3}', |
| | | 'ss': '[0-5][0-9]', |
| | | 's': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
| | | 'mm': '[0-5][0-9]', |
| | | 'm': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
| | | 'HH': '[01][0-9]|2[0-3]', |
| | | 'H': options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]', |
| | | 'hh': '[0][1-9]|[1][012]', |
| | | 'h': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
| | | 'a': 'AM|PM', |
| | | 'EEEE': $locale.DATETIME_FORMATS.DAY.join('|'), |
| | | 'EEE': $locale.DATETIME_FORMATS.SHORTDAY.join('|'), |
| | | 'dd': '0[1-9]|[12][0-9]|3[01]', |
| | | 'd': options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]', |
| | | 'MMMM': $locale.DATETIME_FORMATS.MONTH.join('|'), |
| | | 'MMM': $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), |
| | | 'MM': '0[1-9]|1[012]', |
| | | 'M': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
| | | 'yyyy': '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}', |
| | | 'yy': '[0-9]{2}', |
| | | 'y': options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}' |
| | | }; |
| | | var setFnMap = { |
| | | 'sss': proto.setMilliseconds, |
| | | 'ss': proto.setSeconds, |
| | | 's': proto.setSeconds, |
| | | 'mm': proto.setMinutes, |
| | | 'm': proto.setMinutes, |
| | | 'HH': proto.setHours, |
| | | 'H': proto.setHours, |
| | | 'hh': proto.setHours, |
| | | 'h': proto.setHours, |
| | | 'dd': proto.setDate, |
| | | 'd': proto.setDate, |
| | | 'a': function (value) { |
| | | var hours = this.getHours(); |
| | | return this.setHours(value.match(/pm/i) ? hours + 12 : hours); |
| | | }, |
| | | 'MMMM': function (value) { |
| | | return this.setMonth($locale.DATETIME_FORMATS.MONTH.indexOf(value)); |
| | | }, |
| | | 'MMM': function (value) { |
| | | return this.setMonth($locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value)); |
| | | }, |
| | | 'MM': function (value) { |
| | | return this.setMonth(1 * value - 1); |
| | | }, |
| | | 'M': function (value) { |
| | | return this.setMonth(1 * value - 1); |
| | | }, |
| | | 'yyyy': proto.setFullYear, |
| | | 'yy': function (value) { |
| | | return this.setFullYear(2000 + 1 * value); |
| | | }, |
| | | 'y': proto.setFullYear |
| | | }; |
| | | var regex, setMap; |
| | | $dateParser.init = function () { |
| | | $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format; |
| | | regex = regExpForFormat($dateParser.$format); |
| | | setMap = setMapForFormat($dateParser.$format); |
| | | }; |
| | | $dateParser.isValid = function (date) { |
| | | if (angular.isDate(date)) |
| | | return !isNaN(date.getTime()); |
| | | return regex.test(date); |
| | | }; |
| | | $dateParser.parse = function (value, baseDate, format) { |
| | | var formatRegex = format ? regExpForFormat(format) : regex; |
| | | var formatSetMap = format ? setMapForFormat(format) : setMap; |
| | | if (angular.isDate(value)) |
| | | return value; |
| | | var matches = formatRegex.exec(value); |
| | | if (!matches) |
| | | return false; |
| | | var date = baseDate || new Date(0, 0, 1); |
| | | for (var i = 0; i < matches.length - 1; i++) { |
| | | formatSetMap[i] && formatSetMap[i].call(date, matches[i + 1]); |
| | | } |
| | | return date; |
| | | }; |
| | | // Private functions |
| | | function setMapForFormat(format) { |
| | | var keys = Object.keys(setFnMap), i; |
| | | var map = [], sortedMap = []; |
| | | // Map to setFn |
| | | var clonedFormat = format; |
| | | for (i = 0; i < keys.length; i++) { |
| | | if (format.split(keys[i]).length > 1) { |
| | | var index = clonedFormat.search(keys[i]); |
| | | format = format.split(keys[i]).join(''); |
| | | if (setFnMap[keys[i]]) |
| | | map[index] = setFnMap[keys[i]]; |
| | | } |
| | | } |
| | | // Sort result map |
| | | angular.forEach(map, function (v) { |
| | | sortedMap.push(v); |
| | | }); |
| | | return sortedMap; |
| | | } |
| | | function escapeReservedSymbols(text) { |
| | | return text.replace(/\//g, '[\\/]').replace('/-/g', '[-]').replace(/\./g, '[.]').replace(/\\s/g, '[\\s]'); |
| | | } |
| | | function regExpForFormat(format) { |
| | | var keys = Object.keys(regExpMap), i; |
| | | var re = format; |
| | | // Abstract replaces to avoid collisions |
| | | for (i = 0; i < keys.length; i++) { |
| | | re = re.split(keys[i]).join('${' + i + '}'); |
| | | } |
| | | // Replace abstracted values |
| | | for (i = 0; i < keys.length; i++) { |
| | | re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')'); |
| | | } |
| | | format = escapeReservedSymbols(format); |
| | | return new RegExp('^' + re + '$', ['i']); |
| | | } |
| | | $dateParser.init(); |
| | | return $dateParser; |
| | | }; |
| | | return DateParserFactory; |
| | | } |
| | | ]; |
| | | } |
| | | ]); |
| | | |
| | | // Source: debounce.js |
| | | angular.module('mgcrea.ngStrap.helpers.debounce', []).constant('debounce', function (func, wait, immediate) { |
| | | var timeout, args, context, timestamp, result; |
| | | return function () { |
| | | context = this; |
| | | args = arguments; |
| | | timestamp = new Date(); |
| | | var later = function () { |
| | | var last = new Date() - timestamp; |
| | | if (last < wait) { |
| | | timeout = setTimeout(later, wait - last); |
| | | } else { |
| | | timeout = null; |
| | | if (!immediate) |
| | | result = func.apply(context, args); |
| | | } |
| | | }; |
| | | var callNow = immediate && !timeout; |
| | | if (!timeout) { |
| | | timeout = setTimeout(later, wait); |
| | | } |
| | | if (callNow) |
| | | result = func.apply(context, args); |
| | | return result; |
| | | }; |
| | | }).constant('throttle', function (func, wait, options) { |
| | | var context, args, result; |
| | | var timeout = null; |
| | | var previous = 0; |
| | | options || (options = {}); |
| | | var later = function () { |
| | | previous = options.leading === false ? 0 : new Date(); |
| | | timeout = null; |
| | | result = func.apply(context, args); |
| | | }; |
| | | return function () { |
| | | var now = new Date(); |
| | | if (!previous && options.leading === false) |
| | | previous = now; |
| | | var remaining = wait - (now - previous); |
| | | context = this; |
| | | args = arguments; |
| | | if (remaining <= 0) { |
| | | clearTimeout(timeout); |
| | | timeout = null; |
| | | previous = now; |
| | | result = func.apply(context, args); |
| | | } else if (!timeout && options.trailing !== false) { |
| | | timeout = setTimeout(later, remaining); |
| | | } |
| | | return result; |
| | | }; |
| | | }); |
| | | |
| | | // Source: dimensions.js |
| | | angular.module('mgcrea.ngStrap.helpers.dimensions', []).factory('dimensions', [ |
| | | '$document', |
| | | '$window', |
| | | function ($document, $window) { |
| | | var jqLite = angular.element; |
| | | var fn = {}; |
| | | /** |
| | | * Test the element nodeName |
| | | * @param element |
| | | * @param name |
| | | */ |
| | | var nodeName = fn.nodeName = function (element, name) { |
| | | return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase(); |
| | | }; |
| | | /** |
| | | * Returns the element computed style |
| | | * @param element |
| | | * @param prop |
| | | * @param extra |
| | | */ |
| | | fn.css = function (element, prop, extra) { |
| | | var value; |
| | | if (element.currentStyle) { |
| | | //IE |
| | | value = element.currentStyle[prop]; |
| | | } else if (window.getComputedStyle) { |
| | | value = window.getComputedStyle(element)[prop]; |
| | | } else { |
| | | value = element.style[prop]; |
| | | } |
| | | return extra === true ? parseFloat(value) || 0 : value; |
| | | }; |
| | | /** |
| | | * Provides read-only equivalent of jQuery's offset function: |
| | | * @required-by bootstrap-tooltip, bootstrap-affix |
| | | * @url http://api.jquery.com/offset/ |
| | | * @param element |
| | | */ |
| | | fn.offset = function (element) { |
| | | var boxRect = element.getBoundingClientRect(); |
| | | var docElement = element.ownerDocument; |
| | | return { |
| | | width: boxRect.width || element.offsetWidth, |
| | | height: boxRect.height || element.offsetHeight, |
| | | top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0), |
| | | left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0) |
| | | }; |
| | | }; |
| | | /** |
| | | * Provides read-only equivalent of jQuery's position function |
| | | * @required-by bootstrap-tooltip, bootstrap-affix |
| | | * @url http://api.jquery.com/offset/ |
| | | * @param element |
| | | */ |
| | | fn.position = function (element) { |
| | | var offsetParentRect = { |
| | | top: 0, |
| | | left: 0 |
| | | }, offsetParentElement, offset; |
| | | // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent |
| | | if (fn.css(element, 'position') === 'fixed') { |
| | | // We assume that getBoundingClientRect is available when computed position is fixed |
| | | offset = element.getBoundingClientRect(); |
| | | } else { |
| | | // Get *real* offsetParentElement |
| | | offsetParentElement = offsetParent(element); |
| | | offset = fn.offset(element); |
| | | // Get correct offsets |
| | | offset = fn.offset(element); |
| | | if (!nodeName(offsetParentElement, 'html')) { |
| | | offsetParentRect = fn.offset(offsetParentElement); |
| | | } |
| | | // Add offsetParent borders |
| | | offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true); |
| | | offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true); |
| | | } |
| | | // Subtract parent offsets and element margins |
| | | return { |
| | | width: element.offsetWidth, |
| | | height: element.offsetHeight, |
| | | top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true), |
| | | left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true) |
| | | }; |
| | | }; |
| | | /** |
| | | * Returns the closest, non-statically positioned offsetParent of a given element |
| | | * @required-by fn.position |
| | | * @param element |
| | | */ |
| | | var offsetParent = function offsetParentElement(element) { |
| | | var docElement = element.ownerDocument; |
| | | var offsetParent = element.offsetParent || docElement; |
| | | if (nodeName(offsetParent, '#document')) |
| | | return docElement.documentElement; |
| | | while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') { |
| | | offsetParent = offsetParent.offsetParent; |
| | | } |
| | | return offsetParent || docElement.documentElement; |
| | | }; |
| | | /** |
| | | * Provides equivalent of jQuery's height function |
| | | * @required-by bootstrap-affix |
| | | * @url http://api.jquery.com/height/ |
| | | * @param element |
| | | * @param outer |
| | | */ |
| | | fn.height = function (element, outer) { |
| | | var value = element.offsetHeight; |
| | | if (outer) { |
| | | value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true); |
| | | } else { |
| | | value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true); |
| | | } |
| | | return value; |
| | | }; |
| | | /** |
| | | * Provides equivalent of jQuery's width function |
| | | * @required-by bootstrap-affix |
| | | * @url http://api.jquery.com/width/ |
| | | * @param element |
| | | * @param outer |
| | | */ |
| | | fn.width = function (element, outer) { |
| | | var value = element.offsetWidth; |
| | | if (outer) { |
| | | value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true); |
| | | } else { |
| | | value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true); |
| | | } |
| | | return value; |
| | | }; |
| | | return fn; |
| | | } |
| | | ]); |
| | | |
| | | // Source: parse-options.js |
| | | angular.module('mgcrea.ngStrap.helpers.parseOptions', []).provider('$parseOptions', function () { |
| | | var defaults = this.defaults = { regexp: /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/ }; |
| | | this.$get = [ |
| | | '$parse', |
| | | '$q', |
| | | function ($parse, $q) { |
| | | function ParseOptionsFactory(attr, config) { |
| | | var $parseOptions = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $parseOptions.$values = []; |
| | | // Private vars |
| | | var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn; |
| | | $parseOptions.init = function () { |
| | | $parseOptions.$match = match = attr.match(options.regexp); |
| | | displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], groupByFn = $parse(match[3] || ''), valueFn = $parse(match[2] ? match[1] : valueName), valuesFn = $parse(match[7]); |
| | | }; |
| | | $parseOptions.valuesFn = function (scope, controller) { |
| | | return $q.when(valuesFn(scope, controller)).then(function (values) { |
| | | $parseOptions.$values = values ? parseValues(values, scope) : {}; |
| | | return $parseOptions.$values; |
| | | }); |
| | | }; |
| | | // Private functions |
| | | function parseValues(values, scope) { |
| | | return values.map(function (match, index) { |
| | | var locals = {}, label, value; |
| | | locals[valueName] = match; |
| | | label = displayFn(scope, locals); |
| | | value = valueFn(scope, locals) || index; |
| | | return { |
| | | label: label, |
| | | value: value |
| | | }; |
| | | }); |
| | | } |
| | | $parseOptions.init(); |
| | | return $parseOptions; |
| | | } |
| | | return ParseOptionsFactory; |
| | | } |
| | | ]; |
| | | }); |
| | | |
| | | // Source: raf.js |
| | | angular.version.minor < 3 && angular.version.dot < 14 && angular.module('ng').factory('$$rAF', [ |
| | | '$window', |
| | | '$timeout', |
| | | function ($window, $timeout) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame; |
| | | var cancelAnimationFrame = $window.cancelAnimationFrame || $window.webkitCancelAnimationFrame || $window.mozCancelAnimationFrame || $window.webkitCancelRequestAnimationFrame; |
| | | var rafSupported = !!requestAnimationFrame; |
| | | var raf = rafSupported ? function (fn) { |
| | | var id = requestAnimationFrame(fn); |
| | | return function () { |
| | | cancelAnimationFrame(id); |
| | | }; |
| | | } : function (fn) { |
| | | var timer = $timeout(fn, 16.66, false); |
| | | // 1000 / 60 = 16.666 |
| | | return function () { |
| | | $timeout.cancel(timer); |
| | | }; |
| | | }; |
| | | raf.supported = rafSupported; |
| | | return raf; |
| | | } |
| | | ]); // .factory('$$animateReflow', function($$rAF, $document) { |
| | | // var bodyEl = $document[0].body; |
| | | // return function(fn) { |
| | | // //the returned function acts as the cancellation function |
| | | // return $$rAF(function() { |
| | | // //the line below will force the browser to perform a repaint |
| | | // //so that all the animated elements within the animation frame |
| | | // //will be properly updated and drawn on screen. This is |
| | | // //required to perform multi-class CSS based animations with |
| | | // //Firefox. DO NOT REMOVE THIS LINE. |
| | | // var a = bodyEl.offsetWidth + 1; |
| | | // fn(); |
| | | // }); |
| | | // }; |
| | | // }); |
| | | |
| | | // Source: dropdown.js |
| | | angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip']).provider('$dropdown', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'dropdown', |
| | | placement: 'bottom-left', |
| | | template: 'dropdown/dropdown.tpl.html', |
| | | trigger: 'click', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector; |
| | | function DropdownFactory(element, config) { |
| | | var $dropdown = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | $dropdown = $tooltip(element, options); |
| | | // Protected methods |
| | | $dropdown.$onKeyDown = function (evt) { |
| | | if (!/(38|40)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Retrieve focused index |
| | | var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a')); |
| | | if (!items.length) |
| | | return; |
| | | var index; |
| | | angular.forEach(items, function (el, i) { |
| | | if (matchesSelector && matchesSelector.call(el, ':focus')) |
| | | index = i; |
| | | }); |
| | | // Navigate with keyboard |
| | | if (evt.keyCode === 38 && index > 0) |
| | | index--; |
| | | else if (evt.keyCode === 40 && index < items.length - 1) |
| | | index++; |
| | | else if (angular.isUndefined(index)) |
| | | index = 0; |
| | | items.eq(index)[0].focus(); |
| | | }; |
| | | // Overrides |
| | | var show = $dropdown.show; |
| | | $dropdown.show = function () { |
| | | show(); |
| | | setTimeout(function () { |
| | | options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown); |
| | | bodyEl.on('click', onBodyClick); |
| | | }); |
| | | }; |
| | | var hide = $dropdown.hide; |
| | | $dropdown.hide = function () { |
| | | options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown); |
| | | bodyEl.off('click', onBodyClick); |
| | | hide(); |
| | | }; |
| | | // Private functions |
| | | function onBodyClick(evt) { |
| | | if (evt.target === element[0]) |
| | | return; |
| | | return evt.target !== element[0] && $dropdown.hide(); |
| | | } |
| | | return $dropdown; |
| | | } |
| | | return DropdownFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsDropdown', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$dropdown', |
| | | function ($window, $location, $sce, $dropdown) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) { |
| | | scope.content = newValue; |
| | | }, true); |
| | | // Initialize dropdown |
| | | var dropdown = $dropdown(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | dropdown.destroy(); |
| | | options = null; |
| | | dropdown = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: modal.js |
| | | angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions']).provider('$modal', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | backdropAnimation: 'am-fade', |
| | | prefixClass: 'modal', |
| | | prefixEvent: 'modal', |
| | | placement: 'top', |
| | | template: 'modal/modal.tpl.html', |
| | | contentTemplate: false, |
| | | container: false, |
| | | element: null, |
| | | backdrop: true, |
| | | keyboard: true, |
| | | html: false, |
| | | show: true |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$compile', |
| | | '$q', |
| | | '$templateCache', |
| | | '$http', |
| | | '$animate', |
| | | '$timeout', |
| | | '$sce', |
| | | 'dimensions', |
| | | function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) { |
| | | var forEach = angular.forEach; |
| | | var trim = String.prototype.trim; |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | var bodyElement = angular.element($window.document.body); |
| | | var htmlReplaceRegExp = /ng-bind="/gi; |
| | | function ModalFactory(config) { |
| | | var $modal = {}; |
| | | // Common vars |
| | | var options = $modal.$options = angular.extend({}, defaults, config); |
| | | $modal.$promise = fetchTemplate(options.template); |
| | | var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | if (!options.element && !options.container) { |
| | | options.container = 'body'; |
| | | } |
| | | // Support scope as string options |
| | | forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | if (options[key]) |
| | | scope[key] = $sce.trustAsHtml(options[key]); |
| | | }); |
| | | // Provide scope helpers |
| | | scope.$hide = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.hide(); |
| | | }); |
| | | }; |
| | | scope.$show = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.show(); |
| | | }); |
| | | }; |
| | | scope.$toggle = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.toggle(); |
| | | }); |
| | | }; |
| | | // Support contentTemplate option |
| | | if (options.contentTemplate) { |
| | | $modal.$promise = $modal.$promise.then(function (template) { |
| | | var templateEl = angular.element(template); |
| | | return fetchTemplate(options.contentTemplate).then(function (contentTemplate) { |
| | | var contentEl = findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate); |
| | | // Drop the default footer as you probably don't want it if you use a custom contentTemplate |
| | | if (!config.template) |
| | | contentEl.next().remove(); |
| | | return templateEl[0].outerHTML; |
| | | }); |
| | | }); |
| | | } |
| | | // Fetch, compile then initialize modal |
| | | var modalLinker, modalElement; |
| | | var backdropElement = angular.element('<div class="' + options.prefixClass + '-backdrop"/>'); |
| | | $modal.$promise.then(function (template) { |
| | | if (angular.isObject(template)) |
| | | template = template.data; |
| | | if (options.html) |
| | | template = template.replace(htmlReplaceRegExp, 'ng-bind-html="'); |
| | | template = trim.apply(template); |
| | | modalLinker = $compile(template); |
| | | $modal.init(); |
| | | }); |
| | | $modal.init = function () { |
| | | // Options: show |
| | | if (options.show) { |
| | | scope.$$postDigest(function () { |
| | | $modal.show(); |
| | | }); |
| | | } |
| | | }; |
| | | $modal.destroy = function () { |
| | | // Remove element |
| | | if (modalElement) { |
| | | modalElement.remove(); |
| | | modalElement = null; |
| | | } |
| | | if (backdropElement) { |
| | | backdropElement.remove(); |
| | | backdropElement = null; |
| | | } |
| | | // Destroy scope |
| | | scope.$destroy(); |
| | | }; |
| | | $modal.show = function () { |
| | | scope.$emit(options.prefixEvent + '.show.before', $modal); |
| | | var parent = options.container ? findElement(options.container) : null; |
| | | var after = options.container ? null : options.element; |
| | | // Fetch a cloned element linked from template |
| | | modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) { |
| | | }); |
| | | // Set the initial positioning. |
| | | modalElement.css({ display: 'block' }).addClass(options.placement); |
| | | // Options: animation |
| | | if (options.animation) { |
| | | if (options.backdrop) { |
| | | backdropElement.addClass(options.backdropAnimation); |
| | | } |
| | | modalElement.addClass(options.animation); |
| | | } |
| | | if (options.backdrop) { |
| | | $animate.enter(backdropElement, bodyElement, null, function () { |
| | | }); |
| | | } |
| | | $animate.enter(modalElement, parent, after, function () { |
| | | scope.$emit(options.prefixEvent + '.show', $modal); |
| | | }); |
| | | scope.$isShown = true; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Focus once the enter-animation has started |
| | | // Weird PhantomJS bug hack |
| | | var el = modalElement[0]; |
| | | requestAnimationFrame(function () { |
| | | el.focus(); |
| | | }); |
| | | bodyElement.addClass(options.prefixClass + '-open'); |
| | | if (options.animation) { |
| | | bodyElement.addClass(options.prefixClass + '-with-' + options.animation); |
| | | } |
| | | // Bind events |
| | | if (options.backdrop) { |
| | | modalElement.on('click', hideOnBackdropClick); |
| | | backdropElement.on('click', hideOnBackdropClick); |
| | | } |
| | | if (options.keyboard) { |
| | | modalElement.on('keyup', $modal.$onKeyUp); |
| | | } |
| | | }; |
| | | $modal.hide = function () { |
| | | scope.$emit(options.prefixEvent + '.hide.before', $modal); |
| | | $animate.leave(modalElement, function () { |
| | | scope.$emit(options.prefixEvent + '.hide', $modal); |
| | | bodyElement.removeClass(options.prefixClass + '-open'); |
| | | if (options.animation) { |
| | | bodyElement.addClass(options.prefixClass + '-with-' + options.animation); |
| | | } |
| | | }); |
| | | if (options.backdrop) { |
| | | $animate.leave(backdropElement, function () { |
| | | }); |
| | | } |
| | | scope.$isShown = false; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Unbind events |
| | | if (options.backdrop) { |
| | | modalElement.off('click', hideOnBackdropClick); |
| | | backdropElement.off('click', hideOnBackdropClick); |
| | | } |
| | | if (options.keyboard) { |
| | | modalElement.off('keyup', $modal.$onKeyUp); |
| | | } |
| | | }; |
| | | $modal.toggle = function () { |
| | | scope.$isShown ? $modal.hide() : $modal.show(); |
| | | }; |
| | | $modal.focus = function () { |
| | | modalElement[0].focus(); |
| | | }; |
| | | // Protected methods |
| | | $modal.$onKeyUp = function (evt) { |
| | | evt.which === 27 && $modal.hide(); |
| | | }; |
| | | // Private methods |
| | | function hideOnBackdropClick(evt) { |
| | | if (evt.target !== evt.currentTarget) |
| | | return; |
| | | options.backdrop === 'static' ? $modal.focus() : $modal.hide(); |
| | | } |
| | | return $modal; |
| | | } |
| | | // Helper functions |
| | | function findElement(query, element) { |
| | | return angular.element((element || document).querySelectorAll(query)); |
| | | } |
| | | function fetchTemplate(template) { |
| | | return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) { |
| | | if (angular.isObject(res)) { |
| | | $templateCache.put(template, res.data); |
| | | return res.data; |
| | | } |
| | | return res; |
| | | }); |
| | | } |
| | | return ModalFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsModal', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$modal', |
| | | function ($window, $location, $sce, $modal) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'backdrop', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize modal |
| | | var modal = $modal(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', modal.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | modal.destroy(); |
| | | options = null; |
| | | modal = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: navbar.js |
| | | angular.module('mgcrea.ngStrap.navbar', []).provider('$navbar', function () { |
| | | var defaults = this.defaults = { |
| | | activeClass: 'active', |
| | | routeAttr: 'data-match-route', |
| | | strict: false |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsNavbar', [ |
| | | '$window', |
| | | '$location', |
| | | '$navbar', |
| | | function ($window, $location, $navbar) { |
| | | var defaults = $navbar.defaults; |
| | | return { |
| | | restrict: 'A', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = angular.copy(defaults); |
| | | angular.forEach(Object.keys(defaults), function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Watch for the $location |
| | | scope.$watch(function () { |
| | | return $location.path(); |
| | | }, function (newValue, oldValue) { |
| | | var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']'); |
| | | angular.forEach(liElements, function (li) { |
| | | var liElement = angular.element(li); |
| | | var pattern = liElement.attr(options.routeAttr).replace('/', '\\/'); |
| | | if (options.strict) { |
| | | pattern = '^' + pattern + '$'; |
| | | } |
| | | var regexp = new RegExp(pattern, ['i']); |
| | | if (regexp.test(newValue)) { |
| | | liElement.addClass(options.activeClass); |
| | | } else { |
| | | liElement.removeClass(options.activeClass); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: scrollspy.js |
| | | angular.module('mgcrea.ngStrap.scrollspy', [ |
| | | 'mgcrea.ngStrap.helpers.debounce', |
| | | 'mgcrea.ngStrap.helpers.dimensions' |
| | | ]).provider('$scrollspy', function () { |
| | | // Pool of registered spies |
| | | var spies = this.$$spies = {}; |
| | | var defaults = this.defaults = { |
| | | debounce: 150, |
| | | throttle: 100, |
| | | offset: 100 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | 'dimensions', |
| | | 'debounce', |
| | | 'throttle', |
| | | function ($window, $document, $rootScope, dimensions, debounce, throttle) { |
| | | var windowEl = angular.element($window); |
| | | var docEl = angular.element($document.prop('documentElement')); |
| | | var bodyEl = angular.element($window.document.body); |
| | | // Helper functions |
| | | function nodeName(element, name) { |
| | | return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase(); |
| | | } |
| | | function ScrollSpyFactory(config) { |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | if (!options.element) |
| | | options.element = bodyEl; |
| | | var isWindowSpy = nodeName(options.element, 'body'); |
| | | var scrollEl = isWindowSpy ? windowEl : options.element; |
| | | var scrollId = isWindowSpy ? 'window' : options.id; |
| | | // Use existing spy |
| | | if (spies[scrollId]) { |
| | | spies[scrollId].$$count++; |
| | | return spies[scrollId]; |
| | | } |
| | | var $scrollspy = {}; |
| | | // Private vars |
| | | var unbindViewContentLoaded, unbindIncludeContentLoaded; |
| | | var trackedElements = $scrollspy.$trackedElements = []; |
| | | var sortedElements = []; |
| | | var activeTarget; |
| | | var debouncedCheckPosition; |
| | | var throttledCheckPosition; |
| | | var debouncedCheckOffsets; |
| | | var viewportHeight; |
| | | var scrollTop; |
| | | $scrollspy.init = function () { |
| | | // Setup internal ref counter |
| | | this.$$count = 1; |
| | | // Bind events |
| | | debouncedCheckPosition = debounce(this.checkPosition, options.debounce); |
| | | throttledCheckPosition = throttle(this.checkPosition, options.throttle); |
| | | scrollEl.on('click', this.checkPositionWithEventLoop); |
| | | windowEl.on('resize', debouncedCheckPosition); |
| | | scrollEl.on('scroll', throttledCheckPosition); |
| | | debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce); |
| | | unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets); |
| | | unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets); |
| | | debouncedCheckOffsets(); |
| | | // Register spy for reuse |
| | | if (scrollId) { |
| | | spies[scrollId] = $scrollspy; |
| | | } |
| | | }; |
| | | $scrollspy.destroy = function () { |
| | | // Check internal ref counter |
| | | this.$$count--; |
| | | if (this.$$count > 0) { |
| | | return; |
| | | } |
| | | // Unbind events |
| | | scrollEl.off('click', this.checkPositionWithEventLoop); |
| | | windowEl.off('resize', debouncedCheckPosition); |
| | | scrollEl.off('scroll', debouncedCheckPosition); |
| | | unbindViewContentLoaded(); |
| | | unbindIncludeContentLoaded(); |
| | | if (scrollId) { |
| | | delete spies[scrollId]; |
| | | } |
| | | }; |
| | | $scrollspy.checkPosition = function () { |
| | | // Not ready yet |
| | | if (!sortedElements.length) |
| | | return; |
| | | // Calculate the scroll position |
| | | scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0; |
| | | // Calculate the viewport height for use by the components |
| | | viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight')); |
| | | // Activate first element if scroll is smaller |
| | | if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) { |
| | | return $scrollspy.$activateElement(sortedElements[0]); |
| | | } |
| | | // Activate proper element |
| | | for (var i = sortedElements.length; i--;) { |
| | | if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) |
| | | continue; |
| | | if (activeTarget === sortedElements[i].target) |
| | | continue; |
| | | if (scrollTop < sortedElements[i].offsetTop) |
| | | continue; |
| | | if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) |
| | | continue; |
| | | return $scrollspy.$activateElement(sortedElements[i]); |
| | | } |
| | | }; |
| | | $scrollspy.checkPositionWithEventLoop = function () { |
| | | setTimeout(this.checkPosition, 1); |
| | | }; |
| | | // Protected methods |
| | | $scrollspy.$activateElement = function (element) { |
| | | if (activeTarget) { |
| | | var activeElement = $scrollspy.$getTrackedElement(activeTarget); |
| | | if (activeElement) { |
| | | activeElement.source.removeClass('active'); |
| | | if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) { |
| | | activeElement.source.parent().parent().removeClass('active'); |
| | | } |
| | | } |
| | | } |
| | | activeTarget = element.target; |
| | | element.source.addClass('active'); |
| | | if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) { |
| | | element.source.parent().parent().addClass('active'); |
| | | } |
| | | }; |
| | | $scrollspy.$getTrackedElement = function (target) { |
| | | return trackedElements.filter(function (obj) { |
| | | return obj.target === target; |
| | | })[0]; |
| | | }; |
| | | // Track offsets behavior |
| | | $scrollspy.checkOffsets = function () { |
| | | angular.forEach(trackedElements, function (trackedElement) { |
| | | var targetElement = document.querySelector(trackedElement.target); |
| | | trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null; |
| | | if (options.offset && trackedElement.offsetTop !== null) |
| | | trackedElement.offsetTop -= options.offset * 1; |
| | | }); |
| | | sortedElements = trackedElements.filter(function (el) { |
| | | return el.offsetTop !== null; |
| | | }).sort(function (a, b) { |
| | | return a.offsetTop - b.offsetTop; |
| | | }); |
| | | debouncedCheckPosition(); |
| | | }; |
| | | $scrollspy.trackElement = function (target, source) { |
| | | trackedElements.push({ |
| | | target: target, |
| | | source: source |
| | | }); |
| | | }; |
| | | $scrollspy.untrackElement = function (target, source) { |
| | | var toDelete; |
| | | for (var i = trackedElements.length; i--;) { |
| | | if (trackedElements[i].target === target && trackedElements[i].source === source) { |
| | | toDelete = i; |
| | | break; |
| | | } |
| | | } |
| | | trackedElements = trackedElements.splice(toDelete, 1); |
| | | }; |
| | | $scrollspy.activate = function (i) { |
| | | trackedElements[i].addClass('active'); |
| | | }; |
| | | // Initialize plugin |
| | | $scrollspy.init(); |
| | | return $scrollspy; |
| | | } |
| | | return ScrollSpyFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsScrollspy', [ |
| | | '$rootScope', |
| | | 'debounce', |
| | | 'dimensions', |
| | | '$scrollspy', |
| | | function ($rootScope, debounce, dimensions, $scrollspy) { |
| | | return { |
| | | restrict: 'EAC', |
| | | link: function postLink(scope, element, attr) { |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'offset', |
| | | 'target' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | var scrollspy = $scrollspy(options); |
| | | scrollspy.trackElement(options.target, element); |
| | | scope.$on('$destroy', function () { |
| | | scrollspy.untrackElement(options.target, element); |
| | | scrollspy.destroy(); |
| | | options = null; |
| | | scrollspy = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsScrollspyList', [ |
| | | '$rootScope', |
| | | 'debounce', |
| | | 'dimensions', |
| | | '$scrollspy', |
| | | function ($rootScope, debounce, dimensions, $scrollspy) { |
| | | return { |
| | | restrict: 'A', |
| | | compile: function postLink(element, attr) { |
| | | var children = element[0].querySelectorAll('li > a[href]'); |
| | | angular.forEach(children, function (child) { |
| | | var childEl = angular.element(child); |
| | | childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href')); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: popover.js |
| | | angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).provider('$popover', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | container: false, |
| | | target: false, |
| | | placement: 'right', |
| | | template: 'popover/popover.tpl.html', |
| | | contentTemplate: false, |
| | | trigger: 'click', |
| | | keyboard: true, |
| | | html: false, |
| | | title: '', |
| | | content: '', |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$tooltip', |
| | | function ($tooltip) { |
| | | function PopoverFactory(element, config) { |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var $popover = $tooltip(element, options); |
| | | // Support scope as string options [/*title, */content] |
| | | if (options.content) { |
| | | $popover.$scope.content = options.content; |
| | | } |
| | | return $popover; |
| | | } |
| | | return PopoverFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsPopover', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$popover', |
| | | function ($window, $location, $sce, $popover) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'container', |
| | | 'target', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | angular.isDefined(oldValue) && requestAnimationFrame(function () { |
| | | popover && popover.$applyPlacement(); |
| | | }); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | angular.isDefined(oldValue) && requestAnimationFrame(function () { |
| | | popover && popover.$applyPlacement(); |
| | | }); |
| | | }, true); |
| | | // Initialize popover |
| | | var popover = $popover(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | popover.destroy(); |
| | | options = null; |
| | | popover = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: select.js |
| | | angular.module('mgcrea.ngStrap.select', [ |
| | | 'mgcrea.ngStrap.tooltip', |
| | | 'mgcrea.ngStrap.helpers.parseOptions' |
| | | ]).provider('$select', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'select', |
| | | placement: 'bottom-left', |
| | | template: 'select/select.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | multiple: false, |
| | | sort: true, |
| | | caretHtml: ' <span class="caret"></span>', |
| | | placeholder: 'Choose among the following...', |
| | | maxLength: 3, |
| | | maxLengthHtml: 'selected', |
| | | iconCheckmark: 'glyphicon glyphicon-ok' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | function SelectFactory(element, controller, config) { |
| | | var $select = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $select = $tooltip(element, options); |
| | | var scope = $select.$scope; |
| | | scope.$matches = []; |
| | | scope.$activeIndex = 0; |
| | | scope.$isMultiple = options.multiple; |
| | | scope.$iconCheckmark = options.iconCheckmark; |
| | | scope.$activate = function (index) { |
| | | scope.$$postDigest(function () { |
| | | $select.activate(index); |
| | | }); |
| | | }; |
| | | scope.$select = function (index, evt) { |
| | | scope.$$postDigest(function () { |
| | | $select.select(index); |
| | | }); |
| | | }; |
| | | scope.$isVisible = function () { |
| | | return $select.$isVisible(); |
| | | }; |
| | | scope.$isActive = function (index) { |
| | | return $select.$isActive(index); |
| | | }; |
| | | // Public methods |
| | | $select.update = function (matches) { |
| | | scope.$matches = matches; |
| | | $select.$updateActiveIndex(); |
| | | }; |
| | | $select.activate = function (index) { |
| | | if (options.multiple) { |
| | | scope.$activeIndex.sort(); |
| | | $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index); |
| | | if (options.sort) |
| | | scope.$activeIndex.sort(); |
| | | } else { |
| | | scope.$activeIndex = index; |
| | | } |
| | | return scope.$activeIndex; |
| | | }; |
| | | $select.select = function (index) { |
| | | var value = scope.$matches[index].value; |
| | | scope.$apply(function () { |
| | | $select.activate(index); |
| | | if (options.multiple) { |
| | | controller.$setViewValue(scope.$activeIndex.map(function (index) { |
| | | return scope.$matches[index].value; |
| | | })); |
| | | } else { |
| | | controller.$setViewValue(value); |
| | | // Hide if single select |
| | | $select.hide(); |
| | | } |
| | | }); |
| | | // Emit event |
| | | scope.$emit('$select.select', value, index); |
| | | }; |
| | | // Protected methods |
| | | $select.$updateActiveIndex = function () { |
| | | if (controller.$modelValue && scope.$matches.length) { |
| | | if (options.multiple && angular.isArray(controller.$modelValue)) { |
| | | scope.$activeIndex = controller.$modelValue.map(function (value) { |
| | | return $select.$getIndex(value); |
| | | }); |
| | | } else { |
| | | scope.$activeIndex = $select.$getIndex(controller.$modelValue); |
| | | } |
| | | } else if (scope.$activeIndex >= scope.$matches.length) { |
| | | scope.$activeIndex = options.multiple ? [] : 0; |
| | | } |
| | | }; |
| | | $select.$isVisible = function () { |
| | | if (!options.minLength || !controller) { |
| | | return scope.$matches.length; |
| | | } |
| | | // minLength support |
| | | return scope.$matches.length && controller.$viewValue.length >= options.minLength; |
| | | }; |
| | | $select.$isActive = function (index) { |
| | | if (options.multiple) { |
| | | return scope.$activeIndex.indexOf(index) !== -1; |
| | | } else { |
| | | return scope.$activeIndex === index; |
| | | } |
| | | }; |
| | | $select.$getIndex = function (value) { |
| | | var l = scope.$matches.length, i = l; |
| | | if (!l) |
| | | return; |
| | | for (i = l; i--;) { |
| | | if (scope.$matches[i].value === value) |
| | | break; |
| | | } |
| | | if (i < 0) |
| | | return; |
| | | return i; |
| | | }; |
| | | $select.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $select.$onKeyDown = function (evt) { |
| | | if (!/(9|13|38|40)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Select with enter |
| | | if (!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) { |
| | | return $select.select(scope.$activeIndex); |
| | | } |
| | | // Navigate with keyboard |
| | | if (evt.keyCode === 38 && scope.$activeIndex > 0) |
| | | scope.$activeIndex--; |
| | | else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) |
| | | scope.$activeIndex++; |
| | | else if (angular.isUndefined(scope.$activeIndex)) |
| | | scope.$activeIndex = 0; |
| | | scope.$digest(); |
| | | }; |
| | | // Overrides |
| | | var _show = $select.show; |
| | | $select.show = function () { |
| | | _show(); |
| | | if (options.multiple) { |
| | | $select.$element.addClass('select-multiple'); |
| | | } |
| | | setTimeout(function () { |
| | | $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $select.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $select.hide; |
| | | $select.hide = function () { |
| | | $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $select.$onKeyDown); |
| | | } |
| | | _hide(true); |
| | | }; |
| | | return $select; |
| | | } |
| | | SelectFactory.defaults = defaults; |
| | | return SelectFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsSelect', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$select', |
| | | '$parseOptions', |
| | | function ($window, $parse, $q, $select, $parseOptions) { |
| | | var defaults = $select.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'placeholder', |
| | | 'multiple', |
| | | 'maxLength', |
| | | 'maxLengthHtml' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Add support for select markup |
| | | if (element[0].nodeName.toLowerCase() === 'select') { |
| | | var inputEl = element; |
| | | inputEl.css('display', 'none'); |
| | | element = angular.element('<button type="button" class="btn btn-default"></button>'); |
| | | inputEl.after(element); |
| | | } |
| | | // Build proper ngOptions |
| | | var parsedOptions = $parseOptions(attr.ngOptions); |
| | | // Initialize select |
| | | var select = $select(element, controller, options); |
| | | // Watch ngOptions values before filtering for changes |
| | | var watchedOptions = parsedOptions.$match[7].replace(/\|.+/, '').trim(); |
| | | scope.$watch(watchedOptions, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue); |
| | | parsedOptions.valuesFn(scope, controller).then(function (values) { |
| | | select.update(values); |
| | | controller.$render(); |
| | | }); |
| | | }, true); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue); |
| | | select.$updateActiveIndex(); |
| | | controller.$render(); |
| | | }, true); |
| | | // Model rendering in view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var selected, index; |
| | | if (options.multiple && angular.isArray(controller.$modelValue)) { |
| | | selected = controller.$modelValue.map(function (value) { |
| | | index = select.$getIndex(value); |
| | | return angular.isDefined(index) ? select.$scope.$matches[index].label : false; |
| | | }).filter(angular.isDefined); |
| | | if (selected.length > (options.maxLength || defaults.maxLength)) { |
| | | selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml); |
| | | } else { |
| | | selected = selected.join(', '); |
| | | } |
| | | } else { |
| | | index = select.$getIndex(controller.$modelValue); |
| | | selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false; |
| | | } |
| | | element.html((selected ? selected : attr.placeholder || defaults.placeholder) + defaults.caretHtml); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | select.destroy(); |
| | | options = null; |
| | | select = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: tab.js |
| | | angular.module('mgcrea.ngStrap.tab', []).run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('$pane', '{{pane.content}}'); |
| | | } |
| | | ]).provider('$tab', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | template: 'tab/tab.tpl.html' |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsTabs', [ |
| | | '$window', |
| | | '$animate', |
| | | '$tab', |
| | | function ($window, $animate, $tab) { |
| | | var defaults = $tab.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | require: '?ngModel', |
| | | templateUrl: function (element, attr) { |
| | | return attr.template || defaults.template; |
| | | }, |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = defaults; |
| | | angular.forEach(['animation'], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Require scope as an object |
| | | attr.bsTabs && scope.$watch(attr.bsTabs, function (newValue, oldValue) { |
| | | scope.panes = newValue; |
| | | }, true); |
| | | // Add base class |
| | | element.addClass('tabs'); |
| | | // Support animations |
| | | if (options.animation) { |
| | | element.addClass(options.animation); |
| | | } |
| | | scope.active = scope.activePane = 0; |
| | | // view -> model |
| | | scope.setActive = function (index, ev) { |
| | | scope.active = index; |
| | | if (controller) { |
| | | controller.$setViewValue(index); |
| | | } |
| | | }; |
| | | // model -> view |
| | | if (controller) { |
| | | controller.$render = function () { |
| | | scope.active = controller.$modelValue * 1; |
| | | }; |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: timepicker.js |
| | | angular.module('mgcrea.ngStrap.timepicker', [ |
| | | 'mgcrea.ngStrap.helpers.dateParser', |
| | | 'mgcrea.ngStrap.tooltip' |
| | | ]).provider('$timepicker', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'timepicker', |
| | | placement: 'bottom-left', |
| | | template: 'timepicker/timepicker.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | useNative: true, |
| | | timeType: 'date', |
| | | timeFormat: 'shortTime', |
| | | modelTimeFormat: null, |
| | | autoclose: false, |
| | | minTime: -Infinity, |
| | | maxTime: +Infinity, |
| | | length: 5, |
| | | hourStep: 1, |
| | | minuteStep: 5, |
| | | iconUp: 'glyphicon glyphicon-chevron-up', |
| | | iconDown: 'glyphicon glyphicon-chevron-down' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$sce', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $sce, $locale, dateFilter, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | if (!defaults.lang) |
| | | defaults.lang = $locale.id; |
| | | function timepickerFactory(element, controller, config) { |
| | | var $timepicker = $tooltip(element, angular.extend({}, defaults, config)); |
| | | var parentScope = config.scope; |
| | | var options = $timepicker.$options; |
| | | var scope = $timepicker.$scope; |
| | | // View vars |
| | | var selectedIndex = 0; |
| | | var startDate = controller.$dateValue || new Date(); |
| | | var viewDate = { |
| | | hour: startDate.getHours(), |
| | | meridian: startDate.getHours() < 12, |
| | | minute: startDate.getMinutes(), |
| | | second: startDate.getSeconds(), |
| | | millisecond: startDate.getMilliseconds() |
| | | }; |
| | | var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat; |
| | | var formats = /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1); |
| | | scope.$iconUp = options.iconUp; |
| | | scope.$iconDown = options.iconDown; |
| | | // Scope methods |
| | | scope.$select = function (date, index) { |
| | | $timepicker.select(date, index); |
| | | }; |
| | | scope.$moveIndex = function (value, index) { |
| | | $timepicker.$moveIndex(value, index); |
| | | }; |
| | | scope.$switchMeridian = function (date) { |
| | | $timepicker.switchMeridian(date); |
| | | }; |
| | | // Public methods |
| | | $timepicker.update = function (date) { |
| | | // console.warn('$timepicker.update() newValue=%o', date); |
| | | if (angular.isDate(date) && !isNaN(date.getTime())) { |
| | | $timepicker.$date = date; |
| | | angular.extend(viewDate, { |
| | | hour: date.getHours(), |
| | | minute: date.getMinutes(), |
| | | second: date.getSeconds(), |
| | | millisecond: date.getMilliseconds() |
| | | }); |
| | | $timepicker.$build(); |
| | | } else if (!$timepicker.$isBuilt) { |
| | | $timepicker.$build(); |
| | | } |
| | | }; |
| | | $timepicker.select = function (date, index, keep) { |
| | | // console.warn('$timepicker.select', date, scope.$mode); |
| | | if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) |
| | | controller.$dateValue = new Date(1970, 0, 1); |
| | | if (!angular.isDate(date)) |
| | | date = new Date(date); |
| | | if (index === 0) |
| | | controller.$dateValue.setHours(date.getHours()); |
| | | else if (index === 1) |
| | | controller.$dateValue.setMinutes(date.getMinutes()); |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | if (options.autoclose && !keep) { |
| | | $timepicker.hide(true); |
| | | } |
| | | }; |
| | | $timepicker.switchMeridian = function (date) { |
| | | var hours = (date || controller.$dateValue).getHours(); |
| | | controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12); |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | }; |
| | | // Protected methods |
| | | $timepicker.$build = function () { |
| | | // console.warn('$timepicker.$build() viewDate=%o', viewDate); |
| | | var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10); |
| | | var hours = [], hour; |
| | | for (i = 0; i < options.length; i++) { |
| | | hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep); |
| | | hours.push({ |
| | | date: hour, |
| | | label: dateFilter(hour, formats[0]), |
| | | selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), |
| | | disabled: $timepicker.$isDisabled(hour, 0) |
| | | }); |
| | | } |
| | | var minutes = [], minute; |
| | | for (i = 0; i < options.length; i++) { |
| | | minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep); |
| | | minutes.push({ |
| | | date: minute, |
| | | label: dateFilter(minute, formats[2]), |
| | | selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), |
| | | disabled: $timepicker.$isDisabled(minute, 1) |
| | | }); |
| | | } |
| | | var rows = []; |
| | | for (i = 0; i < options.length; i++) { |
| | | rows.push([ |
| | | hours[i], |
| | | minutes[i] |
| | | ]); |
| | | } |
| | | scope.rows = rows; |
| | | scope.showAM = !!formats[3]; |
| | | scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12; |
| | | scope.timeSeparator = formats[1]; |
| | | $timepicker.$isBuilt = true; |
| | | }; |
| | | $timepicker.$isSelected = function (date, index) { |
| | | if (!$timepicker.$date) |
| | | return false; |
| | | else if (index === 0) { |
| | | return date.getHours() === $timepicker.$date.getHours(); |
| | | } else if (index === 1) { |
| | | return date.getMinutes() === $timepicker.$date.getMinutes(); |
| | | } |
| | | }; |
| | | $timepicker.$isDisabled = function (date, index) { |
| | | var selectedTime; |
| | | if (index === 0) { |
| | | selectedTime = date.getTime() + viewDate.minute * 60000; |
| | | } else if (index === 1) { |
| | | selectedTime = date.getTime() + viewDate.hour * 3600000; |
| | | } |
| | | return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1; |
| | | }; |
| | | $timepicker.$moveIndex = function (value, index) { |
| | | var targetDate; |
| | | if (index === 0) { |
| | | targetDate = new Date(1970, 0, 1, viewDate.hour + value * options.length, viewDate.minute); |
| | | angular.extend(viewDate, { hour: targetDate.getHours() }); |
| | | } else if (index === 1) { |
| | | targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + value * options.length * options.minuteStep); |
| | | angular.extend(viewDate, { minute: targetDate.getMinutes() }); |
| | | } |
| | | $timepicker.$build(); |
| | | }; |
| | | $timepicker.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | if (evt.target.nodeName.toLowerCase() !== 'input') |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | if (targetEl[0].nodeName.toLowerCase() !== 'button') { |
| | | targetEl = targetEl.parent(); |
| | | } |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $timepicker.$onKeyDown = function (evt) { |
| | | if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Close on enter |
| | | if (evt.keyCode === 13) |
| | | return $timepicker.hide(true); |
| | | // Navigate with keyboard |
| | | var newDate = new Date($timepicker.$date); |
| | | var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length; |
| | | var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length; |
| | | var lateralMove = /(37|39)/.test(evt.keyCode); |
| | | var count = 2 + !!formats[3] * 1; |
| | | // Navigate indexes (left, right) |
| | | if (lateralMove) { |
| | | if (evt.keyCode === 37) |
| | | selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1; |
| | | else if (evt.keyCode === 39) |
| | | selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0; |
| | | } |
| | | // Update values (up, down) |
| | | var selectRange = [ |
| | | 0, |
| | | hoursLength |
| | | ]; |
| | | if (selectedIndex === 0) { |
| | | if (evt.keyCode === 38) |
| | | newDate.setHours(hours - parseInt(options.hourStep, 10)); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setHours(hours + parseInt(options.hourStep, 10)); |
| | | selectRange = [ |
| | | 0, |
| | | hoursLength |
| | | ]; |
| | | } else if (selectedIndex === 1) { |
| | | if (evt.keyCode === 38) |
| | | newDate.setMinutes(minutes - parseInt(options.minuteStep, 10)); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setMinutes(minutes + parseInt(options.minuteStep, 10)); |
| | | selectRange = [ |
| | | hoursLength + 1, |
| | | hoursLength + 1 + minutesLength |
| | | ]; |
| | | } else if (selectedIndex === 2) { |
| | | if (!lateralMove) |
| | | $timepicker.switchMeridian(); |
| | | selectRange = [ |
| | | hoursLength + 1 + minutesLength + 1, |
| | | hoursLength + 1 + minutesLength + 3 |
| | | ]; |
| | | } |
| | | $timepicker.select(newDate, selectedIndex, true); |
| | | createSelection(selectRange[0], selectRange[1]); |
| | | parentScope.$digest(); |
| | | }; |
| | | // Private |
| | | function createSelection(start, end) { |
| | | if (element[0].createTextRange) { |
| | | var selRange = element[0].createTextRange(); |
| | | selRange.collapse(true); |
| | | selRange.moveStart('character', start); |
| | | selRange.moveEnd('character', end); |
| | | selRange.select(); |
| | | } else if (element[0].setSelectionRange) { |
| | | element[0].setSelectionRange(start, end); |
| | | } else if (angular.isUndefined(element[0].selectionStart)) { |
| | | element[0].selectionStart = start; |
| | | element[0].selectionEnd = end; |
| | | } |
| | | } |
| | | function focusElement() { |
| | | element[0].focus(); |
| | | } |
| | | // Overrides |
| | | var _init = $timepicker.init; |
| | | $timepicker.init = function () { |
| | | if (isNative && options.useNative) { |
| | | element.prop('type', 'time'); |
| | | element.css('-webkit-appearance', 'textfield'); |
| | | return; |
| | | } else if (isTouch) { |
| | | element.prop('type', 'text'); |
| | | element.attr('readonly', 'true'); |
| | | element.on('click', focusElement); |
| | | } |
| | | _init(); |
| | | }; |
| | | var _destroy = $timepicker.destroy; |
| | | $timepicker.destroy = function () { |
| | | if (isNative && options.useNative) { |
| | | element.off('click', focusElement); |
| | | } |
| | | _destroy(); |
| | | }; |
| | | var _show = $timepicker.show; |
| | | $timepicker.show = function () { |
| | | _show(); |
| | | setTimeout(function () { |
| | | $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $timepicker.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $timepicker.hide; |
| | | $timepicker.hide = function (blur) { |
| | | $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $timepicker.$onKeyDown); |
| | | } |
| | | _hide(blur); |
| | | }; |
| | | return $timepicker; |
| | | } |
| | | timepickerFactory.defaults = defaults; |
| | | return timepickerFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTimepicker', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$timepicker', |
| | | '$dateParser', |
| | | '$timeout', |
| | | function ($window, $parse, $q, $locale, dateFilter, $timepicker, $dateParser, $timeout) { |
| | | var defaults = $timepicker.defaults; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | controller: controller |
| | | }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'autoclose', |
| | | 'timeType', |
| | | 'timeFormat', |
| | | 'modelTimeFormat', |
| | | 'useNative', |
| | | 'hourStep', |
| | | 'minuteStep', |
| | | 'length' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Initialize timepicker |
| | | if (isNative && (options.useNative || defaults.useNative)) |
| | | options.timeFormat = 'HH:mm'; |
| | | var timepicker = $timepicker(element, controller, options); |
| | | options = timepicker.$options; |
| | | // Initialize parser |
| | | var dateParser = $dateParser({ |
| | | format: options.timeFormat, |
| | | lang: options.lang |
| | | }); |
| | | // Observe attributes for changes |
| | | angular.forEach([ |
| | | 'minTime', |
| | | 'maxTime' |
| | | ], function (key) { |
| | | // console.warn('attr.$observe(%s)', key, attr[key]); |
| | | angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) { |
| | | if (newValue === 'now') { |
| | | timepicker.$options[key] = new Date().setFullYear(1970, 0, 1); |
| | | } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) { |
| | | timepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2)); |
| | | } else { |
| | | timepicker.$options[key] = dateParser.parse(newValue, new Date(1970, 0, 1, 0)); |
| | | } |
| | | !isNaN(timepicker.$options[key]) && timepicker.$build(); |
| | | }); |
| | | }); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue); |
| | | timepicker.update(controller.$dateValue); |
| | | }, true); |
| | | // viewValue -> $parsers -> modelValue |
| | | controller.$parsers.unshift(function (viewValue) { |
| | | // console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue); |
| | | // Null values should correctly reset the model value & validity |
| | | if (!viewValue) { |
| | | controller.$setValidity('date', true); |
| | | return; |
| | | } |
| | | var parsedTime = dateParser.parse(viewValue, controller.$dateValue); |
| | | if (!parsedTime || isNaN(parsedTime.getTime())) { |
| | | controller.$setValidity('date', false); |
| | | } else { |
| | | var isValid = parsedTime.getTime() >= options.minTime && parsedTime.getTime() <= options.maxTime; |
| | | controller.$setValidity('date', isValid); |
| | | // Only update the model when we have a valid date |
| | | if (isValid) |
| | | controller.$dateValue = parsedTime; |
| | | } |
| | | if (options.timeType === 'string') { |
| | | return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat); |
| | | } else if (options.timeType === 'number') { |
| | | return controller.$dateValue.getTime(); |
| | | } else if (options.timeType === 'iso') { |
| | | return controller.$dateValue.toISOString(); |
| | | } else { |
| | | return new Date(controller.$dateValue); |
| | | } |
| | | }); |
| | | // modelValue -> $formatters -> viewValue |
| | | controller.$formatters.push(function (modelValue) { |
| | | // console.warn('$formatter("%s"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue); |
| | | var date; |
| | | if (angular.isUndefined(modelValue) || modelValue === null) { |
| | | date = NaN; |
| | | } else if (angular.isDate(modelValue)) { |
| | | date = modelValue; |
| | | } else if (options.timeType === 'string') { |
| | | date = dateParser.parse(modelValue, null, options.modelTimeFormat); |
| | | } else { |
| | | date = new Date(modelValue); |
| | | } |
| | | // Setup default value? |
| | | // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5); |
| | | controller.$dateValue = date; |
| | | return controller.$dateValue; |
| | | }); |
| | | // viewValue -> element |
| | | controller.$render = function () { |
| | | // console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue); |
| | | element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.timeFormat)); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | timepicker.destroy(); |
| | | options = null; |
| | | timepicker = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: tooltip.js |
| | | angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'tooltip', |
| | | prefixEvent: 'tooltip', |
| | | container: false, |
| | | target: false, |
| | | placement: 'top', |
| | | template: 'tooltip/tooltip.tpl.html', |
| | | contentTemplate: false, |
| | | trigger: 'hover focus', |
| | | keyboard: false, |
| | | html: false, |
| | | show: false, |
| | | title: '', |
| | | type: '', |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$compile', |
| | | '$q', |
| | | '$templateCache', |
| | | '$http', |
| | | '$animate', |
| | | 'dimensions', |
| | | '$$rAF', |
| | | function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, dimensions, $$rAF) { |
| | | var trim = String.prototype.trim; |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var htmlReplaceRegExp = /ng-bind="/gi; |
| | | function TooltipFactory(element, config) { |
| | | var $tooltip = {}; |
| | | // Common vars |
| | | var nodeName = element[0].nodeName.toLowerCase(); |
| | | var options = $tooltip.$options = angular.extend({}, defaults, config); |
| | | $tooltip.$promise = fetchTemplate(options.template); |
| | | var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | if (options.delay && angular.isString(options.delay)) { |
| | | options.delay = parseFloat(options.delay); |
| | | } |
| | | // Support scope as string options |
| | | if (options.title) { |
| | | $tooltip.$scope.title = options.title; |
| | | } |
| | | // Provide scope helpers |
| | | scope.$hide = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.hide(); |
| | | }); |
| | | }; |
| | | scope.$show = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.show(); |
| | | }); |
| | | }; |
| | | scope.$toggle = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.toggle(); |
| | | }); |
| | | }; |
| | | $tooltip.$isShown = scope.$isShown = false; |
| | | // Private vars |
| | | var timeout, hoverState; |
| | | // Support contentTemplate option |
| | | if (options.contentTemplate) { |
| | | $tooltip.$promise = $tooltip.$promise.then(function (template) { |
| | | var templateEl = angular.element(template); |
| | | return fetchTemplate(options.contentTemplate).then(function (contentTemplate) { |
| | | var contentEl = findElement('[ng-bind="content"]', templateEl[0]); |
| | | if (!contentEl.length) |
| | | contentEl = findElement('[ng-bind="title"]', templateEl[0]); |
| | | contentEl.removeAttr('ng-bind').html(contentTemplate); |
| | | return templateEl[0].outerHTML; |
| | | }); |
| | | }); |
| | | } |
| | | // Fetch, compile then initialize tooltip |
| | | var tipLinker, tipElement, tipTemplate, tipContainer; |
| | | $tooltip.$promise.then(function (template) { |
| | | if (angular.isObject(template)) |
| | | template = template.data; |
| | | if (options.html) |
| | | template = template.replace(htmlReplaceRegExp, 'ng-bind-html="'); |
| | | template = trim.apply(template); |
| | | tipTemplate = template; |
| | | tipLinker = $compile(template); |
| | | $tooltip.init(); |
| | | }); |
| | | $tooltip.init = function () { |
| | | // Options: delay |
| | | if (options.delay && angular.isNumber(options.delay)) { |
| | | options.delay = { |
| | | show: options.delay, |
| | | hide: options.delay |
| | | }; |
| | | } |
| | | // Replace trigger on touch devices ? |
| | | // if(isTouch && options.trigger === defaults.trigger) { |
| | | // options.trigger.replace(/hover/g, 'click'); |
| | | // } |
| | | // Options : container |
| | | if (options.container === 'self') { |
| | | tipContainer = element; |
| | | } else if (options.container) { |
| | | tipContainer = findElement(options.container); |
| | | } |
| | | // Options: trigger |
| | | var triggers = options.trigger.split(' '); |
| | | angular.forEach(triggers, function (trigger) { |
| | | if (trigger === 'click') { |
| | | element.on('click', $tooltip.toggle); |
| | | } else if (trigger !== 'manual') { |
| | | element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter); |
| | | element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave); |
| | | nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown); |
| | | } |
| | | }); |
| | | // Options: target |
| | | if (options.target) { |
| | | options.target = angular.isElement(options.target) ? options.target : findElement(options.target)[0]; |
| | | } |
| | | // Options: show |
| | | if (options.show) { |
| | | scope.$$postDigest(function () { |
| | | options.trigger === 'focus' ? element[0].focus() : $tooltip.show(); |
| | | }); |
| | | } |
| | | }; |
| | | $tooltip.destroy = function () { |
| | | // Unbind events |
| | | var triggers = options.trigger.split(' '); |
| | | for (var i = triggers.length; i--;) { |
| | | var trigger = triggers[i]; |
| | | if (trigger === 'click') { |
| | | element.off('click', $tooltip.toggle); |
| | | } else if (trigger !== 'manual') { |
| | | element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter); |
| | | element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave); |
| | | nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown); |
| | | } |
| | | } |
| | | // Remove element |
| | | if (tipElement) { |
| | | tipElement.remove(); |
| | | tipElement = null; |
| | | } |
| | | // Cancel pending callbacks |
| | | clearTimeout(timeout); |
| | | // Destroy scope |
| | | scope.$destroy(); |
| | | }; |
| | | $tooltip.enter = function () { |
| | | clearTimeout(timeout); |
| | | hoverState = 'in'; |
| | | if (!options.delay || !options.delay.show) { |
| | | return $tooltip.show(); |
| | | } |
| | | timeout = setTimeout(function () { |
| | | if (hoverState === 'in') |
| | | $tooltip.show(); |
| | | }, options.delay.show); |
| | | }; |
| | | $tooltip.show = function () { |
| | | scope.$emit(options.prefixEvent + '.show.before', $tooltip); |
| | | var parent = options.container ? tipContainer : null; |
| | | var after = options.container ? null : element; |
| | | // Hide any existing tipElement |
| | | if (tipElement) |
| | | tipElement.remove(); |
| | | // Fetch a cloned element linked from template |
| | | tipElement = $tooltip.$element = tipLinker(scope, function (clonedElement, scope) { |
| | | }); |
| | | // Set the initial positioning. |
| | | tipElement.css({ |
| | | top: '-9999px', |
| | | left: '-9999px', |
| | | display: 'block' |
| | | }).addClass(options.placement); |
| | | // Options: animation |
| | | if (options.animation) |
| | | tipElement.addClass(options.animation); |
| | | // Options: type |
| | | if (options.type) |
| | | tipElement.addClass(options.prefixClass + '-' + options.type); |
| | | $animate.enter(tipElement, parent, after, function () { |
| | | scope.$emit(options.prefixEvent + '.show', $tooltip); |
| | | }); |
| | | $tooltip.$isShown = scope.$isShown = true; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | $$rAF($tooltip.$applyPlacement); |
| | | // var a = bodyEl.offsetWidth + 1; ? |
| | | // Bind events |
| | | if (options.keyboard) { |
| | | if (options.trigger !== 'focus') { |
| | | $tooltip.focus(); |
| | | tipElement.on('keyup', $tooltip.$onKeyUp); |
| | | } else { |
| | | element.on('keyup', $tooltip.$onFocusKeyUp); |
| | | } |
| | | } |
| | | }; |
| | | $tooltip.leave = function () { |
| | | clearTimeout(timeout); |
| | | hoverState = 'out'; |
| | | if (!options.delay || !options.delay.hide) { |
| | | return $tooltip.hide(); |
| | | } |
| | | timeout = setTimeout(function () { |
| | | if (hoverState === 'out') { |
| | | $tooltip.hide(); |
| | | } |
| | | }, options.delay.hide); |
| | | }; |
| | | $tooltip.hide = function (blur) { |
| | | if (!$tooltip.$isShown) |
| | | return; |
| | | scope.$emit(options.prefixEvent + '.hide.before', $tooltip); |
| | | $animate.leave(tipElement, function () { |
| | | scope.$emit(options.prefixEvent + '.hide', $tooltip); |
| | | }); |
| | | $tooltip.$isShown = scope.$isShown = false; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Unbind events |
| | | if (options.keyboard && tipElement !== null) { |
| | | tipElement.off('keyup', $tooltip.$onKeyUp); |
| | | } |
| | | // Allow to blur the input when hidden, like when pressing enter key |
| | | if (blur && options.trigger === 'focus') { |
| | | return element[0].blur(); |
| | | } |
| | | }; |
| | | $tooltip.toggle = function () { |
| | | $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter(); |
| | | }; |
| | | $tooltip.focus = function () { |
| | | tipElement[0].focus(); |
| | | }; |
| | | // Protected methods |
| | | $tooltip.$applyPlacement = function () { |
| | | if (!tipElement) |
| | | return; |
| | | // Get the position of the tooltip element. |
| | | var elementPosition = getPosition(); |
| | | // Get the height and width of the tooltip so we can center it. |
| | | var tipWidth = tipElement.prop('offsetWidth'), tipHeight = tipElement.prop('offsetHeight'); |
| | | // Get the tooltip's top and left coordinates to center it with this directive. |
| | | var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight); |
| | | // Now set the calculated positioning. |
| | | tipPosition.top += 'px'; |
| | | tipPosition.left += 'px'; |
| | | tipElement.css(tipPosition); |
| | | }; |
| | | $tooltip.$onKeyUp = function (evt) { |
| | | evt.which === 27 && $tooltip.hide(); |
| | | }; |
| | | $tooltip.$onFocusKeyUp = function (evt) { |
| | | evt.which === 27 && element[0].blur(); |
| | | }; |
| | | $tooltip.$onFocusElementMouseDown = function (evt) { |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Some browsers do not auto-focus buttons (eg. Safari) |
| | | $tooltip.$isShown ? element[0].blur() : element[0].focus(); |
| | | }; |
| | | // Private methods |
| | | function getPosition() { |
| | | if (options.container === 'body') { |
| | | return dimensions.offset(options.target || element[0]); |
| | | } else { |
| | | return dimensions.position(options.target || element[0]); |
| | | } |
| | | } |
| | | function getCalculatedOffset(placement, position, actualWidth, actualHeight) { |
| | | var offset; |
| | | var split = placement.split('-'); |
| | | switch (split[0]) { |
| | | case 'right': |
| | | offset = { |
| | | top: position.top + position.height / 2 - actualHeight / 2, |
| | | left: position.left + position.width |
| | | }; |
| | | break; |
| | | case 'bottom': |
| | | offset = { |
| | | top: position.top + position.height, |
| | | left: position.left + position.width / 2 - actualWidth / 2 |
| | | }; |
| | | break; |
| | | case 'left': |
| | | offset = { |
| | | top: position.top + position.height / 2 - actualHeight / 2, |
| | | left: position.left - actualWidth |
| | | }; |
| | | break; |
| | | default: |
| | | offset = { |
| | | top: position.top - actualHeight, |
| | | left: position.left + position.width / 2 - actualWidth / 2 |
| | | }; |
| | | break; |
| | | } |
| | | if (!split[1]) { |
| | | return offset; |
| | | } |
| | | // Add support for corners @todo css |
| | | if (split[0] === 'top' || split[0] === 'bottom') { |
| | | switch (split[1]) { |
| | | case 'left': |
| | | offset.left = position.left; |
| | | break; |
| | | case 'right': |
| | | offset.left = position.left + position.width - actualWidth; |
| | | } |
| | | } else if (split[0] === 'left' || split[0] === 'right') { |
| | | switch (split[1]) { |
| | | case 'top': |
| | | offset.top = position.top - actualHeight; |
| | | break; |
| | | case 'bottom': |
| | | offset.top = position.top + position.height; |
| | | } |
| | | } |
| | | return offset; |
| | | } |
| | | return $tooltip; |
| | | } |
| | | // Helper functions |
| | | function findElement(query, element) { |
| | | return angular.element((element || document).querySelectorAll(query)); |
| | | } |
| | | function fetchTemplate(template) { |
| | | return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) { |
| | | if (angular.isObject(res)) { |
| | | $templateCache.put(template, res.data); |
| | | return res.data; |
| | | } |
| | | return res; |
| | | }); |
| | | } |
| | | return TooltipFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTooltip', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$tooltip', |
| | | '$$rAF', |
| | | function ($window, $location, $sce, $tooltip, $$rAF) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'container', |
| | | 'target', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'type' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Observe scope attributes for change |
| | | angular.forEach(['title'], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | angular.isDefined(oldValue) && $$rAF(function () { |
| | | tooltip && tooltip.$applyPlacement(); |
| | | }); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsTooltip && scope.$watch(attr.bsTooltip, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.title = newValue; |
| | | } |
| | | angular.isDefined(oldValue) && $$rAF(function () { |
| | | tooltip && tooltip.$applyPlacement(); |
| | | }); |
| | | }, true); |
| | | // Initialize popover |
| | | var tooltip = $tooltip(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | tooltip.destroy(); |
| | | options = null; |
| | | tooltip = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | // Source: typeahead.js |
| | | angular.module('mgcrea.ngStrap.typeahead', [ |
| | | 'mgcrea.ngStrap.tooltip', |
| | | 'mgcrea.ngStrap.helpers.parseOptions' |
| | | ]).provider('$typeahead', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'typeahead', |
| | | placement: 'bottom-left', |
| | | template: 'typeahead/typeahead.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | minLength: 1, |
| | | filter: 'filter', |
| | | limit: 6 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | function TypeaheadFactory(element, controller, config) { |
| | | var $typeahead = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $typeahead = $tooltip(element, options); |
| | | var parentScope = config.scope; |
| | | var scope = $typeahead.$scope; |
| | | scope.$resetMatches = function () { |
| | | scope.$matches = []; |
| | | scope.$activeIndex = 0; |
| | | }; |
| | | scope.$resetMatches(); |
| | | scope.$activate = function (index) { |
| | | scope.$$postDigest(function () { |
| | | $typeahead.activate(index); |
| | | }); |
| | | }; |
| | | scope.$select = function (index, evt) { |
| | | scope.$$postDigest(function () { |
| | | $typeahead.select(index); |
| | | }); |
| | | }; |
| | | scope.$isVisible = function () { |
| | | return $typeahead.$isVisible(); |
| | | }; |
| | | // Public methods |
| | | $typeahead.update = function (matches) { |
| | | scope.$matches = matches; |
| | | if (scope.$activeIndex >= matches.length) { |
| | | scope.$activeIndex = 0; |
| | | } |
| | | }; |
| | | $typeahead.activate = function (index) { |
| | | scope.$activeIndex = index; |
| | | }; |
| | | $typeahead.select = function (index) { |
| | | var value = scope.$matches[index].value; |
| | | controller.$setViewValue(value); |
| | | controller.$render(); |
| | | scope.$resetMatches(); |
| | | if (parentScope) |
| | | parentScope.$digest(); |
| | | // Emit event |
| | | scope.$emit('$typeahead.select', value, index); |
| | | }; |
| | | // Protected methods |
| | | $typeahead.$isVisible = function () { |
| | | if (!options.minLength || !controller) { |
| | | return !!scope.$matches.length; |
| | | } |
| | | // minLength support |
| | | return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength; |
| | | }; |
| | | $typeahead.$getIndex = function (value) { |
| | | var l = scope.$matches.length, i = l; |
| | | if (!l) |
| | | return; |
| | | for (i = l; i--;) { |
| | | if (scope.$matches[i].value === value) |
| | | break; |
| | | } |
| | | if (i < 0) |
| | | return; |
| | | return i; |
| | | }; |
| | | $typeahead.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | }; |
| | | $typeahead.$onKeyDown = function (evt) { |
| | | if (!/(38|40|13)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Select with enter |
| | | if (evt.keyCode === 13 && scope.$matches.length) { |
| | | $typeahead.select(scope.$activeIndex); |
| | | } // Navigate with keyboard |
| | | else if (evt.keyCode === 38 && scope.$activeIndex > 0) |
| | | scope.$activeIndex--; |
| | | else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) |
| | | scope.$activeIndex++; |
| | | else if (angular.isUndefined(scope.$activeIndex)) |
| | | scope.$activeIndex = 0; |
| | | scope.$digest(); |
| | | }; |
| | | // Overrides |
| | | var show = $typeahead.show; |
| | | $typeahead.show = function () { |
| | | show(); |
| | | setTimeout(function () { |
| | | $typeahead.$element.on('mousedown', $typeahead.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $typeahead.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var hide = $typeahead.hide; |
| | | $typeahead.hide = function () { |
| | | $typeahead.$element.off('mousedown', $typeahead.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $typeahead.$onKeyDown); |
| | | } |
| | | hide(); |
| | | }; |
| | | return $typeahead; |
| | | } |
| | | TypeaheadFactory.defaults = defaults; |
| | | return TypeaheadFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTypeahead', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$typeahead', |
| | | '$parseOptions', |
| | | function ($window, $parse, $q, $typeahead, $parseOptions) { |
| | | var defaults = $typeahead.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'filter', |
| | | 'limit', |
| | | 'minLength' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Build proper ngOptions |
| | | var filter = options.filter || defaults.filter; |
| | | var limit = options.limit || defaults.limit; |
| | | var ngOptions = attr.ngOptions; |
| | | if (filter) |
| | | ngOptions += ' | ' + filter + ':$viewValue'; |
| | | if (limit) |
| | | ngOptions += ' | limitTo:' + limit; |
| | | var parsedOptions = $parseOptions(ngOptions); |
| | | // Initialize typeahead |
| | | var typeahead = $typeahead(element, controller, options); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('$watch', element.attr('ng-model'), newValue); |
| | | scope.$modelValue = newValue; |
| | | // Publish modelValue on scope for custom templates |
| | | parsedOptions.valuesFn(scope, controller).then(function (values) { |
| | | if (values.length > limit) |
| | | values = values.slice(0, limit); |
| | | // Do not re-queue an update if a correct value has been selected |
| | | if (values.length === 1 && values[0].value === newValue) |
| | | return; |
| | | typeahead.update(values); |
| | | // Queue a new rendering that will leverage collection loading |
| | | controller.$render(); |
| | | }); |
| | | }); |
| | | // Model rendering in view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | if (controller.$isEmpty(controller.$viewValue)) |
| | | return element.val(''); |
| | | var index = typeahead.$getIndex(controller.$modelValue); |
| | | var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue; |
| | | selected = angular.isObject(selected) ? selected.label : selected; |
| | | element.val(selected.replace(/<(?:.|\n)*?>/gm, '').trim()); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | typeahead.destroy(); |
| | | options = null; |
| | | typeahead = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
| | | |
| | | })(window, document); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | !function(e,t){"use strict";angular.module("mgcrea.ngStrap",["mgcrea.ngStrap.modal","mgcrea.ngStrap.aside","mgcrea.ngStrap.alert","mgcrea.ngStrap.button","mgcrea.ngStrap.select","mgcrea.ngStrap.datepicker","mgcrea.ngStrap.timepicker","mgcrea.ngStrap.navbar","mgcrea.ngStrap.tooltip","mgcrea.ngStrap.popover","mgcrea.ngStrap.dropdown","mgcrea.ngStrap.typeahead","mgcrea.ngStrap.scrollspy","mgcrea.ngStrap.affix","mgcrea.ngStrap.tab"]),angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.helpers.dimensions","mgcrea.ngStrap.helpers.debounce"]).provider("$affix",function(){var e=this.defaults={offsetTop:"auto"};this.$get=["$window","debounce","dimensions",function(t,n,a){function o(o,l){function s(e,t,n){var a=u(),o=c();return h>=a?"top":null!==e&&a+e<=t.top?"middle":null!==v&&t.top+n+g>=o-v?"bottom":"middle"}function u(){return m[0]===t?t.pageYOffset:m[0]===t}function c(){return m[0]===t?t.document.body.scrollHeight:m[0].scrollHeight}var d={},f=angular.extend({},e,l),m=f.target,p="affix affix-top affix-bottom",g=0,$=0,h=0,v=0,y=null,w=null,b=o.parent();if(f.offsetParent)if(f.offsetParent.match(/^\d+$/))for(var k=0;k<1*f.offsetParent-1;k++)b=b.parent();else b=angular.element(f.offsetParent);return d.init=function(){d.$parseOffsets(),$=a.offset(o[0]).top+g,m.on("scroll",d.checkPosition),m.on("click",d.checkPositionWithEventLoop),r.on("resize",d.$debouncedOnResize),d.checkPosition(),d.checkPositionWithEventLoop()},d.destroy=function(){m.off("scroll",d.checkPosition),m.off("click",d.checkPositionWithEventLoop),r.off("resize",d.$debouncedOnResize)},d.checkPositionWithEventLoop=function(){setTimeout(d.checkPosition,1)},d.checkPosition=function(){var e=u(),t=a.offset(o[0]),n=a.height(o[0]),r=s(w,t,n);y!==r&&(y=r,o.removeClass(p).addClass("affix"+("middle"!==r?"-"+r:"")),"top"===r?(w=null,o.css("position",f.offsetParent?"":"relative"),o.css("top","")):"bottom"===r?(w=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,o.css("position",f.offsetParent?"":"relative"),o.css("top",f.offsetParent?"":i[0].offsetHeight-v-n-$+"px")):(w=null,o.css("position","fixed"),o.css("top",g+"px")))},d.$onResize=function(){d.$parseOffsets(),d.checkPosition()},d.$debouncedOnResize=n(d.$onResize,50),d.$parseOffsets=function(){o.css("position",f.offsetParent?"":"relative"),f.offsetTop&&("auto"===f.offsetTop&&(f.offsetTop="+0"),f.offsetTop.match(/^[-+]\d+$/)?(g=1*-f.offsetTop,h=f.offsetParent?a.offset(b[0]).top+1*f.offsetTop:a.offset(o[0]).top-a.css(o[0],"marginTop",!0)+1*f.offsetTop):h=1*f.offsetTop),f.offsetBottom&&(v=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(b[0]).top+a.height(b[0]))+1*f.offsetBottom+1:1*f.offsetBottom)},d.init(),d}var i=angular.element(t.document.body),r=angular.element(t);return o}]}).directive("bsAffix",["$affix","$window",function(e,t){return{restrict:"EAC",require:"^?bsAffixTarget",link:function(n,a,o,i){var r={scope:n,offsetTop:"auto",target:i?i.$element:angular.element(t)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var l=e(a,r);n.$on("$destroy",function(){r=null,l=null})}}}]).directive("bsAffixTarget",function(){return{controller:["$element",function(e){this.$element=e}]}}),angular.module("mgcrea.ngStrap.alert",["mgcrea.ngStrap.modal"]).provider("$alert",function(){var e=this.defaults={animation:"am-fade",prefixClass:"alert",placement:null,template:"alert/alert.tpl.html",container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=["$modal","$timeout",function(t,n){function a(a){var o={},i=angular.extend({},e,a);o=t(i),o.$scope.dismissable=!!i.dismissable,i.type&&(o.$scope.type=i.type);var r=o.show;return i.duration&&(o.show=function(){r(),n(function(){o.hide()},1e3*i.duration)}),o}return a}]}).directive("bsAlert",["$window","$location","$sce","$alert",function(e,t,n,a){e.requestAnimationFrame||e.setTimeout;return{restrict:"EAC",scope:!0,link:function(e,t,o){var i={scope:e,element:t,show:!1};angular.forEach(["template","placement","keyboard","html","container","animation","duration","dismissable"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content","type"],function(t){o[t]&&o.$observe(t,function(a){e[t]=n.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=a(i);t.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r.destroy(),i=null,r=null})}}}]),angular.module("mgcrea.ngStrap.button",[]).provider("$button",function(){var e=this.defaults={activeClass:"active",toggleEvent:"click"};this.$get=function(){return{defaults:e}}}).directive("bsCheckboxGroup",function(){return{restrict:"A",require:"ngModel",compile:function(e,t){e.attr("data-toggle","buttons"),e.removeAttr("ng-model");var n=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(n,function(e){var n=angular.element(e);n.attr("bs-checkbox",""),n.attr("ng-model",t.ngModel+"."+n.attr("value"))})}}}).directive("bsCheckbox",["$button","$$rAF",function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(e,o,i,r){var l=n,s="INPUT"===o[0].nodeName,u=s?o.parent():o,c=angular.isDefined(i.trueValue)?i.trueValue:!0;a.test(i.trueValue)&&(c=e.$eval(i.trueValue));var d=angular.isDefined(i.falseValue)?i.falseValue:!1;a.test(i.falseValue)&&(d=e.$eval(i.falseValue));var f="boolean"!=typeof c||"boolean"!=typeof d;f&&(r.$parsers.push(function(e){return e?c:d}),e.$watch(i.ngModel,function(){r.$render()})),r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){s&&(o[0].checked=e),u.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){s||r.$setViewValue(!u.hasClass("active")),f||r.$render()})})}}}]).directive("bsRadioGroup",function(){return{restrict:"A",require:"ngModel",compile:function(e,t){e.attr("data-toggle","buttons"),e.removeAttr("ng-model");var n=e[0].querySelectorAll('input[type="radio"]');angular.forEach(n,function(e){angular.element(e).attr("bs-radio",""),angular.element(e).attr("ng-model",t.ngModel)})}}}).directive("bsRadio",["$button","$$rAF",function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(e,o,i,r){var l=n,s="INPUT"===o[0].nodeName,u=s?o.parent():o,c=a.test(i.value)?e.$eval(i.value):i.value;r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){s&&(o[0].checked=e),u.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){r.$setViewValue(c),r.$render()})})}}}]),angular.module("mgcrea.ngStrap.aside",["mgcrea.ngStrap.modal"]).provider("$aside",function(){var e=this.defaults={animation:"am-fade-and-slide-right",prefixClass:"aside",placement:"right",template:"aside/aside.tpl.html",contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=["$modal",function(t){function n(n){var a={},o=angular.extend({},e,n);return a=t(o)}return n}]}).directive("bsAside",["$window","$sce","$aside",function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:"EAC",scope:!0,link:function(e,a,o){var i={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r.destroy(),i=null,r=null})}}}]),angular.module("mgcrea.ngStrap.datepicker",["mgcrea.ngStrap.helpers.dateParser","mgcrea.ngStrap.tooltip"]).provider("$datepicker",function(){var e=this.defaults={animation:"am-fade",prefixClass:"datepicker",placement:"bottom-left",template:"datepicker/datepicker.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,useNative:!1,dateType:"date",dateFormat:"shortDate",modelDateFormat:null,dayFormat:"dd",strictFormat:!1,autoclose:!1,minDate:-1/0,maxDate:+1/0,startView:0,minView:0,startWeek:0,iconLeft:"glyphicon glyphicon-chevron-left",iconRight:"glyphicon glyphicon-chevron-right"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","datepickerViews","$tooltip",function(t,n,a,o,i,r,l,s){function u(t,n,a){function o(e){e.selected=r.$isSelected(e.date)}function i(){t[0].focus()}var r=s(t,angular.extend({},e,a)),u=a.scope,f=r.$options,m=r.$scope;f.startView&&(f.startView-=f.minView);var p=l(r);r.$views=p.views;var g=p.viewDate;m.$mode=f.startView,m.$iconLeft=f.iconLeft,m.$iconRight=f.iconRight;var $=r.$views[m.$mode];m.$select=function(e){r.select(e)},m.$selectPane=function(e){r.$selectPane(e)},m.$toggleMode=function(){r.setMode((m.$mode+1)%r.$views.length)},r.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(r.$date=e,$.update.call($,e)),r.$build(!0)},r.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),n.$dateValue.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),!m.$mode||t?(n.$setViewValue(n.$dateValue),n.$render(),f.autoclose&&!t&&r.hide(!0)):(angular.extend(g,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),r.setMode(m.$mode-1),r.$build())},r.setMode=function(e){m.$mode=e,$=r.$views[m.$mode],r.$build()},r.$build=function(e){e===!0&&$.built||(e!==!1||$.built)&&$.build.call($)},r.$updateSelected=function(){for(var e=0,t=m.rows.length;t>e;e++)angular.forEach(m.rows[e],o)},r.$isSelected=function(e){return $.isSelected(e)},r.$selectPane=function(e){var t=$.steps,n=new Date(Date.UTC(g.year+(t.year||0)*e,g.month+(t.month||0)*e,g.date+(t.day||0)*e));angular.extend(g,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),r.$build()},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},r.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return m.$mode?m.$apply(function(){r.setMode(m.$mode-1)}):r.hide(!0);$.onKeyDown(e),u.$digest()}};var h=r.init;r.init=function(){return d&&f.useNative?(t.prop("type","date"),void t.css("-webkit-appearance","textfield")):(c&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",i)),void h())};var v=r.destroy;r.destroy=function(){d&&f.useNative&&t.off("click",i),v()};var y=r.show;r.show=function(){y(),setTimeout(function(){r.$element.on(c?"touchstart":"mousedown",r.$onMouseDown),f.keyboard&&t.on("keydown",r.$onKeyDown)})};var w=r.hide;return r.hide=function(e){r.$element.off(c?"touchstart":"mousedown",r.$onMouseDown),f.keyboard&&t.off("keydown",r.$onKeyDown),w(e)},r}var c=(angular.element(t.document.body),"createTouch"in t.document),d=/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent);return e.lang||(e.lang=i.id),u.defaults=e,u}]}).directive("bsDatepicker",["$window","$parse","$q","$locale","dateFilter","$datepicker","$dateParser","$timeout",function(e,t,n,a,o,i,r){var l=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent)),s=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};return{restrict:"EAC",require:"ngModel",link:function(e,t,n,a){var u={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","useNative","lang","startView","minView"],function(e){angular.isDefined(n[e])&&(u[e]=n[e])}),l&&u.useNative&&(u.dateFormat="yyyy-MM-dd");var c=i(t,a,u);u=c.$options,angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){if("today"===t){var n=new Date;c.$options[e]=+new Date(n.getFullYear(),n.getMonth(),n.getDate()+("maxDate"===e?1:0),0,0,0,"minDate"===e?0:-1)}else c.$options[e]=angular.isString(t)&&t.match(/^".+"$/)?+new Date(t.substr(1,t.length-2)):s(t)?+new Date(parseInt(t,10)):+new Date(t);!isNaN(c.$options[e])&&c.$build(!1)})}),e.$watch(n.ngModel,function(){c.update(a.$dateValue)},!0);var d=r({format:u.dateFormat,lang:u.lang,strict:u.strictFormat});a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=d.parse(e,a.$dateValue);if(!t||isNaN(t.getTime()))return void a.$setValidity("date",!1);var n=isNaN(c.$options.minDate)||t.getTime()>=c.$options.minDate,i=isNaN(c.$options.maxDate)||t.getTime()<=c.$options.maxDate,r=n&&i;return a.$setValidity("date",r),a.$setValidity("min",n),a.$setValidity("max",i),r&&(a.$dateValue=t),"string"===u.dateType?o(t,u.modelDateFormat||u.dateFormat):"number"===u.dateType?a.$dateValue.getTime():"iso"===u.dateType?a.$dateValue.toISOString():new Date(a.$dateValue)}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===u.dateType?d.parse(e,null,u.modelDateFormat):new Date(e),a.$dateValue=t,a.$dateValue}),a.$render=function(){t.val(!a.$dateValue||isNaN(a.$dateValue.getTime())?"":o(a.$dateValue,u.dateFormat))},e.$on("$destroy",function(){c.destroy(),u=null,c=null})}}}]).provider("datepickerViews",function(){function e(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:"dd",daySplit:7};this.$get=["$locale","$sce","dateFilter",function(n,a,o){return function(i){var r=i.$scope,l=i.$options,s=n.DATETIME_FORMATS.SHORTDAY,u=s.slice(l.startWeek).concat(s.slice(0,l.startWeek)),c=a.trustAsHtml('<th class="dow text-center">'+u.join('</th><th class="dow text-center">')+"</th>"),d=i.$date||new Date,f={year:d.getFullYear(),month:d.getMonth(),date:d.getDate()},m=(6e4*d.getTimezoneOffset(),[{format:l.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==f.year||e.getMonth()!==f.month?(angular.extend(f,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getDate()!==f.date&&(f.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(f.year,f.month,1),a=n.getTimezoneOffset(),s=new Date(+n-864e5*t(n.getDay()-l.startWeek,7)),u=s.getTimezoneOffset();u!==a&&(s=new Date(+s+6e4*(u-a)));for(var d,m=[],p=0;42>p;p++)d=new Date(s.getFullYear(),s.getMonth(),s.getDate()+p),m.push({date:d,label:o(d,this.format),selected:i.$date&&this.isSelected(d),muted:d.getMonth()!==f.month,disabled:this.isDisabled(d)});r.title=o(n,"MMMM yyyy"),r.showLabels=!0,r.labels=c,r.rows=e(m,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()&&e.getDate()===i.$date.getDate()},isDisabled:function(e){return e.getTime()<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t,n=i.$date.getTime();37===e.keyCode?t=new Date(n-864e5):38===e.keyCode?t=new Date(n-6048e5):39===e.keyCode?t=new Date(n+864e5):40===e.keyCode&&(t=new Date(n+6048e5)),this.isDisabled(t)||i.select(t,!0)}},{name:"month",format:"MMM",split:4,steps:{year:1},update:function(e){this.built&&e.getFullYear()===f.year?e.getMonth()!==f.month&&(angular.extend(f,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(f,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(f.year,0,1),[]),a=0;12>a;a++)t=new Date(f.year,a,1),n.push({date:t,label:o(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=o(t,"yyyy"),r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return t<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t=i.$date.getMonth(),n=new Date(i.$date);37===e.keyCode?n.setMonth(t-1):38===e.keyCode?n.setMonth(t-4):39===e.keyCode?n.setMonth(t+1):40===e.keyCode&&n.setMonth(t+4),this.isDisabled(n)||i.select(n,!0)}},{name:"year",format:"yyyy",split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(f.year/20,10)?(angular.extend(f,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==f.year&&(angular.extend(f,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=f.year-f.year%(3*this.split),a=[],l=0;12>l;l++)t=new Date(n+l,0,1),a.push({date:t,label:o(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=a[0].label+"-"+a[a.length-1].label,r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return t<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t=i.$date.getFullYear(),n=new Date(i.$date);37===e.keyCode?n.setYear(t-1):38===e.keyCode?n.setYear(t-4):39===e.keyCode?n.setYear(t+1):40===e.keyCode&&n.setYear(t+4),this.isDisabled(n)||i.select(n,!0)}}]);return{views:l.minView?Array.prototype.slice.call(m,l.minView):m,viewDate:f}}}]}),angular.module("mgcrea.ngStrap.helpers.dateParser",[]).provider("$dateParser",["$localeProvider",function(){var e=Date.prototype,t=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale",function(n){var a=function(a){function o(e){var t,n=Object.keys(f),a=[],o=[],i=e;for(t=0;t<n.length;t++)if(e.split(n[t]).length>1){var r=i.search(n[t]);e=e.split(n[t]).join(""),f[n[t]]&&(a[r]=f[n[t]])}return angular.forEach(a,function(e){o.push(e)}),o}function i(e){return e.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function r(e){var t,n=Object.keys(d),a=e;for(t=0;t<n.length;t++)a=a.split(n[t]).join("${"+t+"}");for(t=0;t<n.length;t++)a=a.split("${"+t+"}").join("("+d[n[t]]+")");return e=i(e),new RegExp("^"+a+"$",["i"])}var l,s,u=angular.extend({},t,a),c={},d={sss:"[0-9]{3}",ss:"[0-5][0-9]",s:u.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",mm:"[0-5][0-9]",m:u.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",HH:"[01][0-9]|2[0-3]",H:u.strict?"1?[0-9]|2[0-3]":"[01]?[0-9]|2[0-3]",hh:"[0][1-9]|[1][012]",h:u.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",a:"AM|PM",EEEE:n.DATETIME_FORMATS.DAY.join("|"),EEE:n.DATETIME_FORMATS.SHORTDAY.join("|"),dd:"0[1-9]|[12][0-9]|3[01]",d:u.strict?"[1-9]|[1-2][0-9]|3[01]":"0?[1-9]|[1-2][0-9]|3[01]",MMMM:n.DATETIME_FORMATS.MONTH.join("|"),MMM:n.DATETIME_FORMATS.SHORTMONTH.join("|"),MM:"0[1-9]|1[012]",M:u.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",yyyy:"[1]{1}[0-9]{3}|[2]{1}[0-9]{3}",yy:"[0-9]{2}",y:u.strict?"-?(0|[1-9][0-9]{0,3})":"-?0*[0-9]{1,4}"},f={sss:e.setMilliseconds,ss:e.setSeconds,s:e.setSeconds,mm:e.setMinutes,m:e.setMinutes,HH:e.setHours,H:e.setHours,hh:e.setHours,h:e.setHours,dd:e.setDate,d:e.setDate,a:function(e){var t=this.getHours();return this.setHours(e.match(/pm/i)?t+12:t)},MMMM:function(e){return this.setMonth(n.DATETIME_FORMATS.MONTH.indexOf(e))},MMM:function(e){return this.setMonth(n.DATETIME_FORMATS.SHORTMONTH.indexOf(e))},MM:function(e){return this.setMonth(1*e-1)},M:function(e){return this.setMonth(1*e-1)},yyyy:e.setFullYear,yy:function(e){return this.setFullYear(2e3+1*e)},y:e.setFullYear};return c.init=function(){c.$format=n.DATETIME_FORMATS[u.format]||u.format,l=r(c.$format),s=o(c.$format)},c.isValid=function(e){return angular.isDate(e)?!isNaN(e.getTime()):l.test(e)},c.parse=function(e,t,n){var a=n?r(n):l,i=n?o(n):s;if(angular.isDate(e))return e;var u=a.exec(e);if(!u)return!1;for(var c=t||new Date(0,0,1),d=0;d<u.length-1;d++)i[d]&&i[d].call(c,u[d+1]);return c},c.init(),c};return a}]}]),angular.module("mgcrea.ngStrap.helpers.debounce",[]).constant("debounce",function(e,t,n){var a,o,i,r,l;return function(){i=this,o=arguments,r=new Date;var s=function(){var u=new Date-r;t>u?a=setTimeout(s,t-u):(a=null,n||(l=e.apply(i,o)))},u=n&&!a;return a||(a=setTimeout(s,t)),u&&(l=e.apply(i,o)),l}}).constant("throttle",function(e,t,n){var a,o,i,r=null,l=0;n||(n={});var s=function(){l=n.leading===!1?0:new Date,r=null,i=e.apply(a,o)};return function(){var u=new Date;l||n.leading!==!1||(l=u);var c=t-(u-l);return a=this,o=arguments,0>=c?(clearTimeout(r),r=null,l=u,i=e.apply(a,o)):r||n.trailing===!1||(r=setTimeout(s,c)),i}}),angular.module("mgcrea.ngStrap.helpers.dimensions",[]).factory("dimensions",["$document","$window",function(){var t=(angular.element,{}),n=t.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};t.css=function(t,n,a){var o;return o=t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n],a===!0?parseFloat(o)||0:o},t.offset=function(t){var n=t.getBoundingClientRect(),a=t.ownerDocument;return{width:n.width||t.offsetWidth,height:n.height||t.offsetHeight,top:n.top+(e.pageYOffset||a.documentElement.scrollTop)-(a.documentElement.clientTop||0),left:n.left+(e.pageXOffset||a.documentElement.scrollLeft)-(a.documentElement.clientLeft||0)}},t.position=function(e){var o,i,r={top:0,left:0};return"fixed"===t.css(e,"position")?i=e.getBoundingClientRect():(o=a(e),i=t.offset(e),i=t.offset(e),n(o,"html")||(r=t.offset(o)),r.top+=t.css(o,"borderTopWidth",!0),r.left+=t.css(o,"borderLeftWidth",!0)),{width:e.offsetWidth,height:e.offsetHeight,top:i.top-r.top-t.css(e,"marginTop",!0),left:i.left-r.left-t.css(e,"marginLeft",!0)}};var a=function(e){var a=e.ownerDocument,o=e.offsetParent||a;if(n(o,"#document"))return a.documentElement;for(;o&&!n(o,"html")&&"static"===t.css(o,"position");)o=o.offsetParent;return o||a.documentElement};return t.height=function(e,n){var a=e.offsetHeight;return n?a+=t.css(e,"marginTop",!0)+t.css(e,"marginBottom",!0):a-=t.css(e,"paddingTop",!0)+t.css(e,"paddingBottom",!0)+t.css(e,"borderTopWidth",!0)+t.css(e,"borderBottomWidth",!0),a},t.width=function(e,n){var a=e.offsetWidth;return n?a+=t.css(e,"marginLeft",!0)+t.css(e,"marginRight",!0):a-=t.css(e,"paddingLeft",!0)+t.css(e,"paddingRight",!0)+t.css(e,"borderLeftWidth",!0)+t.css(e,"borderRightWidth",!0),a},t}]),angular.module("mgcrea.ngStrap.helpers.parseOptions",[]).provider("$parseOptions",function(){var e=this.defaults={regexp:/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/};this.$get=["$parse","$q",function(t,n){function a(a,o){function i(e,t){return e.map(function(e,n){var a,o,i={};return i[c]=e,a=u(t,i),o=m(t,i)||n,{label:a,value:o}})}var r={},l=angular.extend({},e,o);r.$values=[];var s,u,c,d,f,m,p;return r.init=function(){r.$match=s=a.match(l.regexp),u=t(s[2]||s[1]),c=s[4]||s[6],d=s[5],f=t(s[3]||""),m=t(s[2]?s[1]:c),p=t(s[7])},r.valuesFn=function(e,t){return n.when(p(e,t)).then(function(t){return r.$values=t?i(t,e):{},r.$values})},r.init(),r}return a}]}),angular.version.minor<3&&angular.version.dot<14&&angular.module("ng").factory("$$rAF",["$window","$timeout",function(e,t){var n=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame,a=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame,o=!!n,i=o?function(e){var t=n(e);return function(){a(t)}}:function(e){var n=t(e,16.66,!1);return function(){t.cancel(n)}};return i.supported=o,i}]),angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var e=this.defaults={animation:"am-fade",prefixClass:"dropdown",placement:"bottom-left",template:"dropdown/dropdown.tpl.html",trigger:"click",container:!1,keyboard:!0,html:!1,delay:0};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function o(t,o){function l(e){return e.target!==t[0]?e.target!==t[0]&&s.hide():void 0}{var s={},u=angular.extend({},e,o);s.$scope=u.scope&&u.scope.$new()||n.$new()}s=a(t,u),s.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(s.$element[0].querySelectorAll("li:not(.divider) a"));if(t.length){var n;angular.forEach(t,function(e,t){r&&r.call(e,":focus")&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&n<t.length-1?n++:angular.isUndefined(n)&&(n=0),t.eq(n)[0].focus()}}};var c=s.show;s.show=function(){c(),setTimeout(function(){u.keyboard&&s.$element.on("keydown",s.$onKeyDown),i.on("click",l)})};var d=s.hide;return s.hide=function(){u.keyboard&&s.$element.off("keydown",s.$onKeyDown),i.off("click",l),d()},s}var i=angular.element(t.document.body),r=Element.prototype.matchesSelector||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector;return o}]}).directive("bsDropdown",["$window","$location","$sce","$dropdown",function(e,t,n,a){return{restrict:"EAC",scope:!0,link:function(e,t,n){var o={scope:e};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template"],function(e){angular.isDefined(n[e])&&(o[e]=n[e])}),n.bsDropdown&&e.$watch(n.bsDropdown,function(t){e.content=t},!0);var i=a(t,o);e.$on("$destroy",function(){i.destroy(),o=null,i=null})}}}]),angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.helpers.dimensions"]).provider("$modal",function(){var e=this.defaults={animation:"am-fade",backdropAnimation:"am-fade",prefixClass:"modal",prefixEvent:"modal",placement:"top",template:"modal/modal.tpl.html",contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","$sce","dimensions",function(n,a,o,i,r,l,s,u,c){function d(t){function n(e){e.target===e.currentTarget&&("static"===r.backdrop?i.focus():i.hide())}var i={},r=i.$options=angular.extend({},e,t);i.$promise=m(r.template);var l=i.$scope=r.scope&&r.scope.$new()||a.$new();r.element||r.container||(r.container="body"),p(["title","content"],function(e){r[e]&&(l[e]=c.trustAsHtml(r[e]))}),l.$hide=function(){l.$$postDigest(function(){i.hide()})},l.$show=function(){l.$$postDigest(function(){i.show()})},l.$toggle=function(){l.$$postDigest(function(){i.toggle()})},r.contentTemplate&&(i.$promise=i.$promise.then(function(e){var n=angular.element(e);return m(r.contentTemplate).then(function(e){var a=f('[ng-bind="content"]',n[0]).removeAttr("ng-bind").html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var u,d,y=angular.element('<div class="'+r.prefixClass+'-backdrop"/>');return i.$promise.then(function(e){angular.isObject(e)&&(e=e.data),r.html&&(e=e.replace(v,'ng-bind-html="')),e=g.apply(e),u=o(e),i.init()}),i.init=function(){r.show&&l.$$postDigest(function(){i.show()})},i.destroy=function(){d&&(d.remove(),d=null),y&&(y.remove(),y=null),l.$destroy()},i.show=function(){l.$emit(r.prefixEvent+".show.before",i);var e=r.container?f(r.container):null,t=r.container?null:r.element;d=i.$element=u(l,function(){}),d.css({display:"block"}).addClass(r.placement),r.animation&&(r.backdrop&&y.addClass(r.backdropAnimation),d.addClass(r.animation)),r.backdrop&&s.enter(y,h,null,function(){}),s.enter(d,e,t,function(){l.$emit(r.prefixEvent+".show",i)}),l.$isShown=!0,l.$$phase||l.$root&&l.$root.$$phase||l.$digest();var a=d[0];$(function(){a.focus()}),h.addClass(r.prefixClass+"-open"),r.animation&&h.addClass(r.prefixClass+"-with-"+r.animation),r.backdrop&&(d.on("click",n),y.on("click",n)),r.keyboard&&d.on("keyup",i.$onKeyUp)},i.hide=function(){l.$emit(r.prefixEvent+".hide.before",i),s.leave(d,function(){l.$emit(r.prefixEvent+".hide",i),h.removeClass(r.prefixClass+"-open"),r.animation&&h.addClass(r.prefixClass+"-with-"+r.animation)}),r.backdrop&&s.leave(y,function(){}),l.$isShown=!1,l.$$phase||l.$root&&l.$root.$$phase||l.$digest(),r.backdrop&&(d.off("click",n),y.off("click",n)),r.keyboard&&d.off("keyup",i.$onKeyUp)},i.toggle=function(){l.$isShown?i.hide():i.show()},i.focus=function(){d[0].focus()},i.$onKeyUp=function(e){27===e.which&&i.hide()},i}function f(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return i.when(r.get(e)||l.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var p=angular.forEach,g=String.prototype.trim,$=n.requestAnimationFrame||n.setTimeout,h=angular.element(n.document.body),v=/ng-bind="/gi;return d}]}).directive("bsModal",["$window","$location","$sce","$modal",function(e,t,n,a){return{restrict:"EAC",scope:!0,link:function(e,t,o){var i={scope:e,element:t,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(t){o[t]&&o.$observe(t,function(a){e[t]=n.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=a(i);t.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r.destroy(),i=null,r=null})}}}]),angular.module("mgcrea.ngStrap.navbar",[]).provider("$navbar",function(){var e=this.defaults={activeClass:"active",routeAttr:"data-match-route",strict:!1};this.$get=function(){return{defaults:e}}}).directive("bsNavbar",["$window","$location","$navbar",function(e,t,n){var a=n.defaults;return{restrict:"A",link:function(e,n,o){var i=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),e.$watch(function(){return t.path()},function(e){var t=n[0].querySelectorAll("li["+i.routeAttr+"]");angular.forEach(t,function(t){var n=angular.element(t),a=n.attr(i.routeAttr).replace("/","\\/");i.strict&&(a="^"+a+"$");var o=new RegExp(a,["i"]);o.test(e)?n.addClass(i.activeClass):n.removeClass(i.activeClass)})})}}}]),angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.helpers.debounce","mgcrea.ngStrap.helpers.dimensions"]).provider("$scrollspy",function(){var e=this.$$spies={},n=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(a,o,i,r,l,s){function u(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function c(o){var c=angular.extend({},n,o);c.element||(c.element=m);var p=u(c.element,"body"),g=p?d:c.element,$=p?"window":c.id;if(e[$])return e[$].$$count++,e[$];var h,v,y,w,b,k,D,T,x={},S=x.$trackedElements=[],M=[];return x.init=function(){this.$$count=1,w=l(this.checkPosition,c.debounce),b=s(this.checkPosition,c.throttle),g.on("click",this.checkPositionWithEventLoop),d.on("resize",w),g.on("scroll",b),k=l(this.checkOffsets,c.debounce),h=i.$on("$viewContentLoaded",k),v=i.$on("$includeContentLoaded",k),k(),$&&(e[$]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(g.off("click",this.checkPositionWithEventLoop),d.off("resize",w),g.off("scroll",w),h(),v(),$&&delete e[$])},x.checkPosition=function(){if(M.length){if(T=(p?a.pageYOffset:g.prop("scrollTop"))||0,D=Math.max(a.innerHeight,f.prop("clientHeight")),T<M[0].offsetTop&&y!==M[0].target)return x.$activateElement(M[0]);for(var e=M.length;e--;)if(!angular.isUndefined(M[e].offsetTop)&&null!==M[e].offsetTop&&y!==M[e].target&&!(T<M[e].offsetTop||M[e+1]&&T>M[e+1].offsetTop))return x.$activateElement(M[e])}},x.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},x.$activateElement=function(e){if(y){var t=x.$getTrackedElement(y);t&&(t.source.removeClass("active"),u(t.source,"li")&&u(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}y=e.target,e.source.addClass("active"),u(e.source,"li")&&u(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},x.$getTrackedElement=function(e){return S.filter(function(t){return t.target===e})[0]},x.checkOffsets=function(){angular.forEach(S,function(e){var n=t.querySelector(e.target);e.offsetTop=n?r.offset(n).top:null,c.offset&&null!==e.offsetTop&&(e.offsetTop-=1*c.offset)}),M=S.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),w() |
| | | },x.trackElement=function(e,t){S.push({target:e,source:t})},x.untrackElement=function(e,t){for(var n,a=S.length;a--;)if(S[a].target===e&&S[a].source===t){n=a;break}S=S.splice(n,1)},x.activate=function(e){S[e].addClass("active")},x.init(),x}var d=angular.element(a),f=angular.element(o.prop("documentElement")),m=angular.element(a.document.body);return c}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(e,t,n,a){return{restrict:"EAC",link:function(e,t,n){var o={scope:e};angular.forEach(["offset","target"],function(e){angular.isDefined(n[e])&&(o[e]=n[e])});var i=a(o);i.trackElement(o.target,t),e.$on("$destroy",function(){i.untrackElement(o.target,t),i.destroy(),o=null,i=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,function(e){var t=angular.element(e);t.parent().attr("bs-scrollspy","").attr("data-target",t.attr("href"))})}}}]),angular.module("mgcrea.ngStrap.popover",["mgcrea.ngStrap.tooltip"]).provider("$popover",function(){var e=this.defaults={animation:"am-fade",container:!1,target:!1,placement:"right",template:"popover/popover.tpl.html",contentTemplate:!1,trigger:"click",keyboard:!0,html:!1,title:"",content:"",delay:0};this.$get=["$tooltip",function(t){function n(n,a){var o=angular.extend({},e,a),i=t(n,o);return o.content&&(i.$scope.content=o.content),i}return n}]}).directive("bsPopover",["$window","$location","$sce","$popover",function(e,t,n,a){var o=e.requestAnimationFrame||e.setTimeout;return{restrict:"EAC",scope:!0,link:function(e,t,i){var r={scope:e};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),angular.forEach(["title","content"],function(t){i[t]&&i.$observe(t,function(a,i){e[t]=n.trustAsHtml(a),angular.isDefined(i)&&o(function(){l&&l.$applyPlacement()})})}),i.bsPopover&&e.$watch(i.bsPopover,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t,angular.isDefined(n)&&o(function(){l&&l.$applyPlacement()})},!0);var l=a(t,r);e.$on("$destroy",function(){l.destroy(),r=null,l=null})}}}]),angular.module("mgcrea.ngStrap.select",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$select",function(){var e=this.defaults={animation:"am-fade",prefixClass:"select",placement:"bottom-left",template:"select/select.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,sort:!0,caretHtml:' <span class="caret"></span>',placeholder:"Choose among the following...",maxLength:3,maxLengthHtml:"selected",iconCheckmark:"glyphicon glyphicon-ok"};this.$get=["$window","$document","$rootScope","$tooltip",function(t,n,a,o){function i(t,n,a){var i={},l=angular.extend({},e,a);i=o(t,l);var s=i.$scope;s.$matches=[],s.$activeIndex=0,s.$isMultiple=l.multiple,s.$iconCheckmark=l.iconCheckmark,s.$activate=function(e){s.$$postDigest(function(){i.activate(e)})},s.$select=function(e){s.$$postDigest(function(){i.select(e)})},s.$isVisible=function(){return i.$isVisible()},s.$isActive=function(e){return i.$isActive(e)},i.update=function(e){s.$matches=e,i.$updateActiveIndex()},i.activate=function(e){return l.multiple?(s.$activeIndex.sort(),i.$isActive(e)?s.$activeIndex.splice(s.$activeIndex.indexOf(e),1):s.$activeIndex.push(e),l.sort&&s.$activeIndex.sort()):s.$activeIndex=e,s.$activeIndex},i.select=function(e){var t=s.$matches[e].value;s.$apply(function(){i.activate(e),l.multiple?n.$setViewValue(s.$activeIndex.map(function(e){return s.$matches[e].value})):(n.$setViewValue(t),i.hide())}),s.$emit("$select.select",t,e)},i.$updateActiveIndex=function(){n.$modelValue&&s.$matches.length?s.$activeIndex=l.multiple&&angular.isArray(n.$modelValue)?n.$modelValue.map(function(e){return i.$getIndex(e)}):i.$getIndex(n.$modelValue):s.$activeIndex>=s.$matches.length&&(s.$activeIndex=l.multiple?[]:0)},i.$isVisible=function(){return l.minLength&&n?s.$matches.length&&n.$viewValue.length>=l.minLength:s.$matches.length},i.$isActive=function(e){return l.multiple?-1!==s.$activeIndex.indexOf(e):s.$activeIndex===e},i.$getIndex=function(e){var t=s.$matches.length,n=t;if(t){for(n=t;n--&&s.$matches[n].value!==e;);if(!(0>n))return n}},i.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),r){var t=angular.element(e.target);t.triggerHandler("click")}},i.$onKeyDown=function(e){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!l.multiple&&(13===e.keyCode||9===e.keyCode))return i.select(s.$activeIndex);38===e.keyCode&&s.$activeIndex>0?s.$activeIndex--:40===e.keyCode&&s.$activeIndex<s.$matches.length-1?s.$activeIndex++:angular.isUndefined(s.$activeIndex)&&(s.$activeIndex=0),s.$digest()}};var u=i.show;i.show=function(){u(),l.multiple&&i.$element.addClass("select-multiple"),setTimeout(function(){i.$element.on(r?"touchstart":"mousedown",i.$onMouseDown),l.keyboard&&t.on("keydown",i.$onKeyDown)})};var c=i.hide;return i.hide=function(){i.$element.off(r?"touchstart":"mousedown",i.$onMouseDown),l.keyboard&&t.off("keydown",i.$onKeyDown),c(!0)},i}var r=(angular.element(t.document.body),"createTouch"in t.document);return i.defaults=e,i}]}).directive("bsSelect",["$window","$parse","$q","$select","$parseOptions",function(e,t,n,a,o){var i=a.defaults;return{restrict:"EAC",require:"ngModel",link:function(e,t,n,r){var l={scope:e};if(angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","placeholder","multiple","maxLength","maxLengthHtml"],function(e){angular.isDefined(n[e])&&(l[e]=n[e])}),"select"===t[0].nodeName.toLowerCase()){var s=t;s.css("display","none"),t=angular.element('<button type="button" class="btn btn-default"></button>'),s.after(t)}var u=o(n.ngOptions),c=a(t,r,l),d=u.$match[7].replace(/\|.+/,"").trim();e.$watch(d,function(){u.valuesFn(e,r).then(function(e){c.update(e),r.$render()})},!0),e.$watch(n.ngModel,function(){c.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,a;l.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return a=c.$getIndex(e),angular.isDefined(a)?c.$scope.$matches[a].label:!1}).filter(angular.isDefined),e=e.length>(l.maxLength||i.maxLength)?e.length+" "+(l.maxLengthHtml||i.maxLengthHtml):e.join(", ")):(a=c.$getIndex(r.$modelValue),e=angular.isDefined(a)?c.$scope.$matches[a].label:!1),t.html((e?e:n.placeholder||i.placeholder)+i.caretHtml)},e.$on("$destroy",function(){c.destroy(),l=null,c=null})}}}]),angular.module("mgcrea.ngStrap.tab",[]).run(["$templateCache",function(e){e.put("$pane","{{pane.content}}")}]).provider("$tab",function(){var e=this.defaults={animation:"am-fade",template:"tab/tab.tpl.html"};this.$get=function(){return{defaults:e}}}).directive("bsTabs",["$window","$animate","$tab",function(e,t,n){var a=n.defaults;return{restrict:"EAC",scope:!0,require:"?ngModel",templateUrl:function(e,t){return t.template||a.template},link:function(e,t,n,o){var i=a;angular.forEach(["animation"],function(e){angular.isDefined(n[e])&&(i[e]=n[e])}),n.bsTabs&&e.$watch(n.bsTabs,function(t){e.panes=t},!0),t.addClass("tabs"),i.animation&&t.addClass(i.animation),e.active=e.activePane=0,e.setActive=function(t){e.active=t,o&&o.$setViewValue(t)},o&&(o.$render=function(){e.active=1*o.$modelValue})}}}]),angular.module("mgcrea.ngStrap.timepicker",["mgcrea.ngStrap.helpers.dateParser","mgcrea.ngStrap.tooltip"]).provider("$timepicker",function(){var e=this.defaults={animation:"am-fade",prefixClass:"timepicker",placement:"bottom-left",template:"timepicker/timepicker.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,useNative:!0,timeType:"date",timeFormat:"shortTime",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,iconUp:"glyphicon glyphicon-chevron-up",iconDown:"glyphicon glyphicon-chevron-down"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","$tooltip",function(t,n,a,o,i,r,l){function s(t,n,a){function o(e,n){if(t[0].createTextRange){var a=t[0].createTextRange();a.collapse(!0),a.moveStart("character",e),a.moveEnd("character",n),a.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,n):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=n)}function s(){t[0].focus()}var d=l(t,angular.extend({},e,a)),f=a.scope,m=d.$options,p=d.$scope,g=0,$=n.$dateValue||new Date,h={hour:$.getHours(),meridian:$.getHours()<12,minute:$.getMinutes(),second:$.getSeconds(),millisecond:$.getMilliseconds()},v=i.DATETIME_FORMATS[m.timeFormat]||m.timeFormat,y=/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(v).slice(1);p.$iconUp=m.iconUp,p.$iconDown=m.iconDown,p.$select=function(e,t){d.select(e,t)},p.$moveIndex=function(e,t){d.$moveIndex(e,t)},p.$switchMeridian=function(e){d.switchMeridian(e)},d.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(d.$date=e,angular.extend(h,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),d.$build()):d.$isBuilt||d.$build()},d.select=function(e,t,a){(!n.$dateValue||isNaN(n.$dateValue.getTime()))&&(n.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?n.$dateValue.setHours(e.getHours()):1===t&&n.$dateValue.setMinutes(e.getMinutes()),n.$setViewValue(n.$dateValue),n.$render(),m.autoclose&&!a&&d.hide(!0)},d.switchMeridian=function(e){var t=(e||n.$dateValue).getHours();n.$dateValue.setHours(12>t?t+12:t-12),n.$setViewValue(n.$dateValue),n.$render()},d.$build=function(){var e,t,n=p.midIndex=parseInt(m.length/2,10),a=[];for(e=0;e<m.length;e++)t=new Date(1970,0,1,h.hour-(n-e)*m.hourStep),a.push({date:t,label:r(t,y[0]),selected:d.$date&&d.$isSelected(t,0),disabled:d.$isDisabled(t,0)});var o,i=[];for(e=0;e<m.length;e++)o=new Date(1970,0,1,0,h.minute-(n-e)*m.minuteStep),i.push({date:o,label:r(o,y[2]),selected:d.$date&&d.$isSelected(o,1),disabled:d.$isDisabled(o,1)});var l=[];for(e=0;e<m.length;e++)l.push([a[e],i[e]]);p.rows=l,p.showAM=!!y[3],p.isAM=(d.$date||a[n].date).getHours()<12,p.timeSeparator=y[1],d.$isBuilt=!0},d.$isSelected=function(e,t){return d.$date?0===t?e.getHours()===d.$date.getHours():1===t?e.getMinutes()===d.$date.getMinutes():void 0:!1},d.$isDisabled=function(e,t){var n;return 0===t?n=e.getTime()+6e4*h.minute:1===t&&(n=e.getTime()+36e5*h.hour),n<1*m.minTime||n>1*m.maxTime},d.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,h.hour+e*m.length,h.minute),angular.extend(h,{hour:n.getHours()})):1===t&&(n=new Date(1970,0,1,h.hour,h.minute+e*m.length*m.minuteStep),angular.extend(h,{minute:n.getMinutes()})),d.$build()},d.$onMouseDown=function(e){if("input"!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),u){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},d.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return d.hide(!0);var t=new Date(d.$date),n=t.getHours(),a=r(t,"h").length,i=t.getMinutes(),l=r(t,"mm").length,s=/(37|39)/.test(e.keyCode),u=2+1*!!y[3];s&&(37===e.keyCode?g=1>g?u-1:g-1:39===e.keyCode&&(g=u-1>g?g+1:0));var c=[0,a];0===g?(38===e.keyCode?t.setHours(n-parseInt(m.hourStep,10)):40===e.keyCode&&t.setHours(n+parseInt(m.hourStep,10)),c=[0,a]):1===g?(38===e.keyCode?t.setMinutes(i-parseInt(m.minuteStep,10)):40===e.keyCode&&t.setMinutes(i+parseInt(m.minuteStep,10)),c=[a+1,a+1+l]):2===g&&(s||d.switchMeridian(),c=[a+1+l+1,a+1+l+3]),d.select(t,g,!0),o(c[0],c[1]),f.$digest()}};var w=d.init;d.init=function(){return c&&m.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(u&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",s)),void w())};var b=d.destroy;d.destroy=function(){c&&m.useNative&&t.off("click",s),b()};var k=d.show;d.show=function(){k(),setTimeout(function(){d.$element.on(u?"touchstart":"mousedown",d.$onMouseDown),m.keyboard&&t.on("keydown",d.$onKeyDown)})};var D=d.hide;return d.hide=function(e){d.$element.off(u?"touchstart":"mousedown",d.$onMouseDown),m.keyboard&&t.off("keydown",d.$onKeyDown),D(e)},d}var u=(angular.element(t.document.body),"createTouch"in t.document),c=/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent);return e.lang||(e.lang=i.id),s.defaults=e,s}]}).directive("bsTimepicker",["$window","$parse","$q","$locale","dateFilter","$timepicker","$dateParser","$timeout",function(e,t,n,a,o,i,r){{var l=i.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:"EAC",require:"ngModel",link:function(e,t,n,a){var u={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","modelTimeFormat","useNative","hourStep","minuteStep","length"],function(e){angular.isDefined(n[e])&&(u[e]=n[e])}),s&&(u.useNative||l.useNative)&&(u.timeFormat="HH:mm");var c=i(t,a,u);u=c.$options;var d=r({format:u.timeFormat,lang:u.lang});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){c.$options[e]="now"===t?(new Date).setFullYear(1970,0,1):angular.isString(t)&&t.match(/^".+"$/)?+new Date(t.substr(1,t.length-2)):d.parse(t,new Date(1970,0,1,0)),!isNaN(c.$options[e])&&c.$build()})}),e.$watch(n.ngModel,function(){c.update(a.$dateValue)},!0),a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=d.parse(e,a.$dateValue);if(!t||isNaN(t.getTime()))a.$setValidity("date",!1);else{var n=t.getTime()>=u.minTime&&t.getTime()<=u.maxTime;a.$setValidity("date",n),n&&(a.$dateValue=t)}return"string"===u.timeType?o(t,u.modelTimeFormat||u.timeFormat):"number"===u.timeType?a.$dateValue.getTime():"iso"===u.timeType?a.$dateValue.toISOString():new Date(a.$dateValue)}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===u.timeType?d.parse(e,null,u.modelTimeFormat):new Date(e),a.$dateValue=t,a.$dateValue}),a.$render=function(){t.val(!a.$dateValue||isNaN(a.$dateValue.getTime())?"":o(a.$dateValue,u.timeFormat))},e.$on("$destroy",function(){c.destroy(),u=null,c=null})}}}]),angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.helpers.dimensions"]).provider("$tooltip",function(){var e=this.defaults={animation:"am-fade",prefixClass:"tooltip",prefixEvent:"tooltip",container:!1,target:!1,placement:"top",template:"tooltip/tooltip.tpl.html",contentTemplate:!1,trigger:"hover focus",keyboard:!1,html:!1,show:!1,title:"",type:"",delay:0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","dimensions","$$rAF",function(n,a,o,i,r,l,s,u,c){function d(t,n){function i(){return"body"===h.container?u.offset(h.target||t[0]):u.position(h.target||t[0])}function r(e,t,n,a){var o,i=e.split("-");switch(i[0]){case"right":o={top:t.top+t.height/2-a/2,left:t.left+t.width};break;case"bottom":o={top:t.top+t.height,left:t.left+t.width/2-n/2};break;case"left":o={top:t.top+t.height/2-a/2,left:t.left-n};break;default:o={top:t.top-a,left:t.left+t.width/2-n/2}}if(!i[1])return o;if("top"===i[0]||"bottom"===i[0])switch(i[1]){case"left":o.left=t.left;break;case"right":o.left=t.left+t.width-n}else if("left"===i[0]||"right"===i[0])switch(i[1]){case"top":o.top=t.top-a;break;case"bottom":o.top=t.top+t.height}return o}var l={},d=t[0].nodeName.toLowerCase(),h=l.$options=angular.extend({},e,n);l.$promise=m(h.template);var v=l.$scope=h.scope&&h.scope.$new()||a.$new();h.delay&&angular.isString(h.delay)&&(h.delay=parseFloat(h.delay)),h.title&&(l.$scope.title=h.title),v.$hide=function(){v.$$postDigest(function(){l.hide()})},v.$show=function(){v.$$postDigest(function(){l.show()})},v.$toggle=function(){v.$$postDigest(function(){l.toggle()})},l.$isShown=v.$isShown=!1;var y,w;h.contentTemplate&&(l.$promise=l.$promise.then(function(e){var t=angular.element(e);return m(h.contentTemplate).then(function(e){var n=f('[ng-bind="content"]',t[0]);return n.length||(n=f('[ng-bind="title"]',t[0])),n.removeAttr("ng-bind").html(e),t[0].outerHTML})}));var b,k,D,T;return l.$promise.then(function(e){angular.isObject(e)&&(e=e.data),h.html&&(e=e.replace($,'ng-bind-html="')),e=p.apply(e),D=e,b=o(e),l.init()}),l.init=function(){h.delay&&angular.isNumber(h.delay)&&(h.delay={show:h.delay,hide:h.delay}),"self"===h.container?T=t:h.container&&(T=f(h.container));var e=h.trigger.split(" ");angular.forEach(e,function(e){"click"===e?t.on("click",l.toggle):"manual"!==e&&(t.on("hover"===e?"mouseenter":"focus",l.enter),t.on("hover"===e?"mouseleave":"blur",l.leave),"button"===d&&"hover"!==e&&t.on(g?"touchstart":"mousedown",l.$onFocusElementMouseDown))}),h.target&&(h.target=angular.isElement(h.target)?h.target:f(h.target)[0]),h.show&&v.$$postDigest(function(){"focus"===h.trigger?t[0].focus():l.show()})},l.destroy=function(){for(var e=h.trigger.split(" "),n=e.length;n--;){var a=e[n];"click"===a?t.off("click",l.toggle):"manual"!==a&&(t.off("hover"===a?"mouseenter":"focus",l.enter),t.off("hover"===a?"mouseleave":"blur",l.leave),"button"===d&&"hover"!==a&&t.off(g?"touchstart":"mousedown",l.$onFocusElementMouseDown))}k&&(k.remove(),k=null),clearTimeout(y),v.$destroy()},l.enter=function(){return clearTimeout(y),w="in",h.delay&&h.delay.show?void(y=setTimeout(function(){"in"===w&&l.show()},h.delay.show)):l.show()},l.show=function(){v.$emit(h.prefixEvent+".show.before",l);var e=h.container?T:null,n=h.container?null:t;k&&k.remove(),k=l.$element=b(v,function(){}),k.css({top:"-9999px",left:"-9999px",display:"block"}).addClass(h.placement),h.animation&&k.addClass(h.animation),h.type&&k.addClass(h.prefixClass+"-"+h.type),s.enter(k,e,n,function(){v.$emit(h.prefixEvent+".show",l)}),l.$isShown=v.$isShown=!0,v.$$phase||v.$root&&v.$root.$$phase||v.$digest(),c(l.$applyPlacement),h.keyboard&&("focus"!==h.trigger?(l.focus(),k.on("keyup",l.$onKeyUp)):t.on("keyup",l.$onFocusKeyUp))},l.leave=function(){return clearTimeout(y),w="out",h.delay&&h.delay.hide?void(y=setTimeout(function(){"out"===w&&l.hide()},h.delay.hide)):l.hide()},l.hide=function(e){return l.$isShown?(v.$emit(h.prefixEvent+".hide.before",l),s.leave(k,function(){v.$emit(h.prefixEvent+".hide",l)}),l.$isShown=v.$isShown=!1,v.$$phase||v.$root&&v.$root.$$phase||v.$digest(),h.keyboard&&null!==k&&k.off("keyup",l.$onKeyUp),e&&"focus"===h.trigger?t[0].blur():void 0):void 0},l.toggle=function(){l.$isShown?l.leave():l.enter()},l.focus=function(){k[0].focus()},l.$applyPlacement=function(){if(k){var e=i(),t=k.prop("offsetWidth"),n=k.prop("offsetHeight"),a=r(h.placement,e,t,n);a.top+="px",a.left+="px",k.css(a)}},l.$onKeyUp=function(e){27===e.which&&l.hide()},l.$onFocusKeyUp=function(e){27===e.which&&t[0].blur()},l.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),l.$isShown?t[0].blur():t[0].focus()},l}function f(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return i.when(r.get(e)||l.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var p=String.prototype.trim,g="createTouch"in n.document,$=/ng-bind="/gi;return d}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip","$$rAF",function(e,t,n,a,o){return{restrict:"EAC",scope:!0,link:function(e,t,i){var r={scope:e};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),angular.forEach(["title"],function(t){i[t]&&i.$observe(t,function(a,i){e[t]=n.trustAsHtml(a),angular.isDefined(i)&&o(function(){l&&l.$applyPlacement()})})}),i.bsTooltip&&e.$watch(i.bsTooltip,function(t,n){angular.isObject(t)?angular.extend(e,t):e.title=t,angular.isDefined(n)&&o(function(){l&&l.$applyPlacement()})},!0);var l=a(t,r);e.$on("$destroy",function(){l.destroy(),r=null,l=null})}}}]),angular.module("mgcrea.ngStrap.typeahead",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$typeahead",function(){var e=this.defaults={animation:"am-fade",prefixClass:"typeahead",placement:"bottom-left",template:"typeahead/typeahead.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,minLength:1,filter:"filter",limit:6};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function o(t,n,o){var i={},r=angular.extend({},e,o);i=a(t,r);var l=o.scope,s=i.$scope;s.$resetMatches=function(){s.$matches=[],s.$activeIndex=0},s.$resetMatches(),s.$activate=function(e){s.$$postDigest(function(){i.activate(e)})},s.$select=function(e){s.$$postDigest(function(){i.select(e)})},s.$isVisible=function(){return i.$isVisible()},i.update=function(e){s.$matches=e,s.$activeIndex>=e.length&&(s.$activeIndex=0)},i.activate=function(e){s.$activeIndex=e},i.select=function(e){var t=s.$matches[e].value;n.$setViewValue(t),n.$render(),s.$resetMatches(),l&&l.$digest(),s.$emit("$typeahead.select",t,e)},i.$isVisible=function(){return r.minLength&&n?s.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=r.minLength:!!s.$matches.length},i.$getIndex=function(e){var t=s.$matches.length,n=t;if(t){for(n=t;n--&&s.$matches[n].value!==e;);if(!(0>n))return n}},i.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},i.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(e.preventDefault(),e.stopPropagation(),13===e.keyCode&&s.$matches.length?i.select(s.$activeIndex):38===e.keyCode&&s.$activeIndex>0?s.$activeIndex--:40===e.keyCode&&s.$activeIndex<s.$matches.length-1?s.$activeIndex++:angular.isUndefined(s.$activeIndex)&&(s.$activeIndex=0),s.$digest())};var u=i.show;i.show=function(){u(),setTimeout(function(){i.$element.on("mousedown",i.$onMouseDown),r.keyboard&&t.on("keydown",i.$onKeyDown)})};var c=i.hide;return i.hide=function(){i.$element.off("mousedown",i.$onMouseDown),r.keyboard&&t.off("keydown",i.$onKeyDown),c()},i}angular.element(t.document.body);return o.defaults=e,o}]}).directive("bsTypeahead",["$window","$parse","$q","$typeahead","$parseOptions",function(e,t,n,a,o){var i=a.defaults;return{restrict:"EAC",require:"ngModel",link:function(e,t,n,r){var l={scope:e};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","filter","limit","minLength"],function(e){angular.isDefined(n[e])&&(l[e]=n[e])});var s=l.filter||i.filter,u=l.limit||i.limit,c=n.ngOptions;s&&(c+=" | "+s+":$viewValue"),u&&(c+=" | limitTo:"+u);var d=o(c),f=a(t,r,l);e.$watch(n.ngModel,function(t){e.$modelValue=t,d.valuesFn(e,r).then(function(e){e.length>u&&(e=e.slice(0,u)),(1!==e.length||e[0].value!==t)&&(f.update(e),r.$render())})}),r.$render=function(){if(r.$isEmpty(r.$viewValue))return t.val("");var e=f.$getIndex(r.$modelValue),n=angular.isDefined(e)?f.$scope.$matches[e].label:r.$viewValue;n=angular.isObject(n)?n.label:n,t.val(n.replace(/<(?:.|\n)*?>/gm,"").trim())},e.$on("$destroy",function(){f.destroy(),l=null,f=null})}}}])}(window,document); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | (function(window, document, undefined) { |
| | | 'use strict'; |
| | | |
| | | // Source: alert.tpl.js |
| | | angular.module('mgcrea.ngStrap.alert').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('alert/alert.tpl.html', '<div class="alert" tabindex="-1" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">×</button> <strong ng-bind="title"></strong> <span ng-bind-html="content"></span></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: aside.tpl.js |
| | | angular.module('mgcrea.ngStrap.aside').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('aside/aside.tpl.html', '<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: datepicker.tpl.js |
| | | angular.module('mgcrea.ngStrap.datepicker').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('datepicker/datepicker.tpl.html', '<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: dropdown.tpl.js |
| | | angular.module('mgcrea.ngStrap.dropdown').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: modal.tpl.js |
| | | angular.module('mgcrea.ngStrap.modal').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('modal/modal.tpl.html', '<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: popover.tpl.js |
| | | angular.module('mgcrea.ngStrap.popover').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('popover/popover.tpl.html', '<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: select.tpl.js |
| | | angular.module('mgcrea.ngStrap.select').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('select/select.tpl.html', '<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><span ng-bind="match.label"></span> <i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i></a></li></ul>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: tab.tpl.js |
| | | angular.module('mgcrea.ngStrap.tab').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('tab/tab.tpl.html', '<ul class="nav nav-tabs"><li ng-repeat="pane in panes" ng-class="{active: $index == active}"><a data-toggle="tab" ng-click="setActive($index, $event)" data-index="{{$index}}" ng-bind-html="pane.title"></a></li></ul><div class="tab-content"><div ng-repeat="pane in panes" class="tab-pane" ng-class="[$index == active ? \'active\' : \'\']" ng-include="pane.template || \'$pane\'"></div></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: timepicker.tpl.js |
| | | angular.module('mgcrea.ngStrap.timepicker').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('timepicker/timepicker.tpl.html', '<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 0)"><i class="{{$iconUp}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 1)"><i class="{{$iconUp}}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td ng-if="showAM"> </td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 0)"><i class="{{$iconDown}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 1)"><i class="{{$iconDown}}"></i></button></th></tr></tfoot></table></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: tooltip.tpl.js |
| | | angular.module('mgcrea.ngStrap.tooltip').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('tooltip/tooltip.tpl.html', '<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>'); |
| | | } |
| | | ]); |
| | | |
| | | // Source: typeahead.tpl.js |
| | | angular.module('mgcrea.ngStrap.typeahead').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('typeahead/typeahead.tpl.html', '<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>'); |
| | | } |
| | | ]); |
| | | |
| | | |
| | | })(window, document); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | !function(){"use strict";angular.module("mgcrea.ngStrap.alert").run(["$templateCache",function(t){t.put("alert/alert.tpl.html",'<div class="alert" tabindex="-1" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">×</button> <strong ng-bind="title"></strong> <span ng-bind-html="content"></span></div>')}]),angular.module("mgcrea.ngStrap.aside").run(["$templateCache",function(t){t.put("aside/aside.tpl.html",'<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]),angular.module("mgcrea.ngStrap.datepicker").run(["$templateCache",function(t){t.put("datepicker/datepicker.tpl.html",'<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>')}]),angular.module("mgcrea.ngStrap.dropdown").run(["$templateCache",function(t){t.put("dropdown/dropdown.tpl.html",'<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>')}]),angular.module("mgcrea.ngStrap.modal").run(["$templateCache",function(t){t.put("modal/modal.tpl.html",'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]),angular.module("mgcrea.ngStrap.popover").run(["$templateCache",function(t){t.put("popover/popover.tpl.html",'<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>')}]),angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(t){t.put("select/select.tpl.html",'<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><span ng-bind="match.label"></span> <i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i></a></li></ul>')}]),angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(t){t.put("tab/tab.tpl.html",'<ul class="nav nav-tabs"><li ng-repeat="pane in panes" ng-class="{active: $index == active}"><a data-toggle="tab" ng-click="setActive($index, $event)" data-index="{{$index}}" ng-bind-html="pane.title"></a></li></ul><div class="tab-content"><div ng-repeat="pane in panes" class="tab-pane" ng-class="[$index == active ? \'active\' : \'\']" ng-include="pane.template || \'$pane\'"></div></div>')}]),angular.module("mgcrea.ngStrap.timepicker").run(["$templateCache",function(t){t.put("timepicker/timepicker.tpl.html",'<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 0)"><i class="{{$iconUp}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 1)"><i class="{{$iconUp}}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td ng-if="showAM"> </td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 0)"><i class="{{$iconDown}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 1)"><i class="{{$iconDown}}"></i></button></th></tr></tfoot></table></div>')}]),angular.module("mgcrea.ngStrap.tooltip").run(["$templateCache",function(t){t.put("tooltip/tooltip.tpl.html",'<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>')}]),angular.module("mgcrea.ngStrap.typeahead").run(["$templateCache",function(t){t.put("typeahead/typeahead.tpl.html",'<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>')}])}(window,document); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.affix', [ |
| | | 'mgcrea.ngStrap.helpers.dimensions', |
| | | 'mgcrea.ngStrap.helpers.debounce' |
| | | ]).provider('$affix', function () { |
| | | var defaults = this.defaults = { offsetTop: 'auto' }; |
| | | this.$get = [ |
| | | '$window', |
| | | 'debounce', |
| | | 'dimensions', |
| | | function ($window, debounce, dimensions) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var windowEl = angular.element($window); |
| | | function AffixFactory(element, config) { |
| | | var $affix = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var targetEl = options.target; |
| | | // Initial private vars |
| | | var reset = 'affix affix-top affix-bottom', initialAffixTop = 0, initialOffsetTop = 0, offsetTop = 0, offsetBottom = 0, affixed = null, unpin = null; |
| | | var parent = element.parent(); |
| | | // Options: custom parent |
| | | if (options.offsetParent) { |
| | | if (options.offsetParent.match(/^\d+$/)) { |
| | | for (var i = 0; i < options.offsetParent * 1 - 1; i++) { |
| | | parent = parent.parent(); |
| | | } |
| | | } else { |
| | | parent = angular.element(options.offsetParent); |
| | | } |
| | | } |
| | | $affix.init = function () { |
| | | $affix.$parseOffsets(); |
| | | initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop; |
| | | // Bind events |
| | | targetEl.on('scroll', $affix.checkPosition); |
| | | targetEl.on('click', $affix.checkPositionWithEventLoop); |
| | | windowEl.on('resize', $affix.$debouncedOnResize); |
| | | // Both of these checkPosition() calls are necessary for the case where |
| | | // the user hits refresh after scrolling to the bottom of the page. |
| | | $affix.checkPosition(); |
| | | $affix.checkPositionWithEventLoop(); |
| | | }; |
| | | $affix.destroy = function () { |
| | | // Unbind events |
| | | targetEl.off('scroll', $affix.checkPosition); |
| | | targetEl.off('click', $affix.checkPositionWithEventLoop); |
| | | windowEl.off('resize', $affix.$debouncedOnResize); |
| | | }; |
| | | $affix.checkPositionWithEventLoop = function () { |
| | | setTimeout($affix.checkPosition, 1); |
| | | }; |
| | | $affix.checkPosition = function () { |
| | | // if (!this.$element.is(':visible')) return |
| | | var scrollTop = getScrollTop(); |
| | | var position = dimensions.offset(element[0]); |
| | | var elementHeight = dimensions.height(element[0]); |
| | | // Get required affix class according to position |
| | | var affix = getRequiredAffixClass(unpin, position, elementHeight); |
| | | // Did affix status changed this last check? |
| | | if (affixed === affix) |
| | | return; |
| | | affixed = affix; |
| | | // Add proper affix class |
| | | element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : '')); |
| | | if (affix === 'top') { |
| | | unpin = null; |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | element.css('top', ''); |
| | | } else if (affix === 'bottom') { |
| | | if (options.offsetUnpin) { |
| | | unpin = -(options.offsetUnpin * 1); |
| | | } else { |
| | | // Calculate unpin threshold when affixed to bottom. |
| | | // Hopefully the browser scrolls pixel by pixel. |
| | | unpin = position.top - scrollTop; |
| | | } |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px'); |
| | | } else { |
| | | // affix === 'middle' |
| | | unpin = null; |
| | | element.css('position', 'fixed'); |
| | | element.css('top', initialAffixTop + 'px'); |
| | | } |
| | | }; |
| | | $affix.$onResize = function () { |
| | | $affix.$parseOffsets(); |
| | | $affix.checkPosition(); |
| | | }; |
| | | $affix.$debouncedOnResize = debounce($affix.$onResize, 50); |
| | | $affix.$parseOffsets = function () { |
| | | // Reset position to calculate correct offsetTop |
| | | element.css('position', options.offsetParent ? '' : 'relative'); |
| | | if (options.offsetTop) { |
| | | if (options.offsetTop === 'auto') { |
| | | options.offsetTop = '+0'; |
| | | } |
| | | if (options.offsetTop.match(/^[-+]\d+$/)) { |
| | | initialAffixTop = -options.offsetTop * 1; |
| | | if (options.offsetParent) { |
| | | offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1; |
| | | } else { |
| | | offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1; |
| | | } |
| | | } else { |
| | | offsetTop = options.offsetTop * 1; |
| | | } |
| | | } |
| | | if (options.offsetBottom) { |
| | | if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) { |
| | | // add 1 pixel due to rounding problems... |
| | | offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1; |
| | | } else { |
| | | offsetBottom = options.offsetBottom * 1; |
| | | } |
| | | } |
| | | }; |
| | | // Private methods |
| | | function getRequiredAffixClass(unpin, position, elementHeight) { |
| | | var scrollTop = getScrollTop(); |
| | | var scrollHeight = getScrollHeight(); |
| | | if (scrollTop <= offsetTop) { |
| | | return 'top'; |
| | | } else if (unpin !== null && scrollTop + unpin <= position.top) { |
| | | return 'middle'; |
| | | } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) { |
| | | return 'bottom'; |
| | | } else { |
| | | return 'middle'; |
| | | } |
| | | } |
| | | function getScrollTop() { |
| | | return targetEl[0] === $window ? $window.pageYOffset : targetEl[0] === $window; |
| | | } |
| | | function getScrollHeight() { |
| | | return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight; |
| | | } |
| | | $affix.init(); |
| | | return $affix; |
| | | } |
| | | return AffixFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAffix', [ |
| | | '$affix', |
| | | '$window', |
| | | function ($affix, $window) { |
| | | return { |
| | | restrict: 'EAC', |
| | | require: '^?bsAffixTarget', |
| | | link: function postLink(scope, element, attr, affixTarget) { |
| | | var options = { |
| | | scope: scope, |
| | | offsetTop: 'auto', |
| | | target: affixTarget ? affixTarget.$element : angular.element($window) |
| | | }; |
| | | angular.forEach([ |
| | | 'offsetTop', |
| | | 'offsetBottom', |
| | | 'offsetParent', |
| | | 'offsetUnpin' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | var affix = $affix(element, options); |
| | | scope.$on('$destroy', function () { |
| | | options = null; |
| | | affix = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsAffixTarget', function () { |
| | | return { |
| | | controller: [ |
| | | '$element', |
| | | function ($element) { |
| | | this.$element = $element; |
| | | } |
| | | ] |
| | | }; |
| | | }); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.helpers.dimensions","mgcrea.ngStrap.helpers.debounce"]).provider("$affix",function(){var t=this.defaults={offsetTop:"auto"};this.$get=["$window","debounce","dimensions",function(e,o,n){function f(f,r){function c(t,e,o){var n=a(),f=l();return P>=n?"top":null!==t&&n+t<=e.top?"middle":null!==$&&e.top+o+h>=f-$?"bottom":"middle"}function a(){return d[0]===e?e.pageYOffset:d[0]===e}function l(){return d[0]===e?e.document.body.scrollHeight:d[0].scrollHeight}var u={},p=angular.extend({},t,r),d=p.target,m="affix affix-top affix-bottom",h=0,g=0,P=0,$=0,v=null,T=null,x=f.parent();if(p.offsetParent)if(p.offsetParent.match(/^\d+$/))for(var b=0;b<1*p.offsetParent-1;b++)x=x.parent();else x=angular.element(p.offsetParent);return u.init=function(){u.$parseOffsets(),g=n.offset(f[0]).top+h,d.on("scroll",u.checkPosition),d.on("click",u.checkPositionWithEventLoop),i.on("resize",u.$debouncedOnResize),u.checkPosition(),u.checkPositionWithEventLoop()},u.destroy=function(){d.off("scroll",u.checkPosition),d.off("click",u.checkPositionWithEventLoop),i.off("resize",u.$debouncedOnResize)},u.checkPositionWithEventLoop=function(){setTimeout(u.checkPosition,1)},u.checkPosition=function(){var t=a(),e=n.offset(f[0]),o=n.height(f[0]),i=c(T,e,o);v!==i&&(v=i,f.removeClass(m).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(T=null,f.css("position",p.offsetParent?"":"relative"),f.css("top","")):"bottom"===i?(T=p.offsetUnpin?-(1*p.offsetUnpin):e.top-t,f.css("position",p.offsetParent?"":"relative"),f.css("top",p.offsetParent?"":s[0].offsetHeight-$-o-g+"px")):(T=null,f.css("position","fixed"),f.css("top",h+"px")))},u.$onResize=function(){u.$parseOffsets(),u.checkPosition()},u.$debouncedOnResize=o(u.$onResize,50),u.$parseOffsets=function(){f.css("position",p.offsetParent?"":"relative"),p.offsetTop&&("auto"===p.offsetTop&&(p.offsetTop="+0"),p.offsetTop.match(/^[-+]\d+$/)?(h=1*-p.offsetTop,P=p.offsetParent?n.offset(x[0]).top+1*p.offsetTop:n.offset(f[0]).top-n.css(f[0],"marginTop",!0)+1*p.offsetTop):P=1*p.offsetTop),p.offsetBottom&&($=p.offsetParent&&p.offsetBottom.match(/^[-+]\d+$/)?l()-(n.offset(x[0]).top+n.height(x[0]))+1*p.offsetBottom+1:1*p.offsetBottom)},u.init(),u}var s=angular.element(e.document.body),i=angular.element(e);return f}]}).directive("bsAffix",["$affix","$window",function(t,e){return{restrict:"EAC",require:"^?bsAffixTarget",link:function(o,n,f,s){var i={scope:o,offsetTop:"auto",target:s?s.$element:angular.element(e)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(t){angular.isDefined(f[t])&&(i[t]=f[t])});var r=t(n,i);o.$on("$destroy",function(){i=null,r=null})}}}]).directive("bsAffixTarget",function(){return{controller:["$element",function(t){this.$element=t}]}}); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | // @BUG: following snippet won't compile correctly |
| | | // @TODO: submit issue to core |
| | | // '<span ng-if="title"><strong ng-bind="title"></strong> </span><span ng-bind-html="content"></span>' + |
| | | angular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal']).provider('$alert', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'alert', |
| | | placement: null, |
| | | template: 'alert/alert.tpl.html', |
| | | container: false, |
| | | element: null, |
| | | backdrop: false, |
| | | keyboard: true, |
| | | show: true, |
| | | duration: false, |
| | | type: false, |
| | | dismissable: true |
| | | }; |
| | | this.$get = [ |
| | | '$modal', |
| | | '$timeout', |
| | | function ($modal, $timeout) { |
| | | function AlertFactory(config) { |
| | | var $alert = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $alert = $modal(options); |
| | | // Support scope as string options [/*title, content, */ type, dismissable] |
| | | $alert.$scope.dismissable = !!options.dismissable; |
| | | if (options.type) { |
| | | $alert.$scope.type = options.type; |
| | | } |
| | | // Support auto-close duration |
| | | var show = $alert.show; |
| | | if (options.duration) { |
| | | $alert.show = function () { |
| | | show(); |
| | | $timeout(function () { |
| | | $alert.hide(); |
| | | }, options.duration * 1000); |
| | | }; |
| | | } |
| | | return $alert; |
| | | } |
| | | return AlertFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAlert', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$alert', |
| | | function ($window, $location, $sce, $alert) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'placement', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation', |
| | | 'duration', |
| | | 'dismissable' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content', |
| | | 'type' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsAlert && scope.$watch(attr.bsAlert, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize alert |
| | | var alert = $alert(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', alert.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | alert.destroy(); |
| | | options = null; |
| | | alert = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.alert",["mgcrea.ngStrap.modal"]).provider("$alert",function(){var t=this.defaults={animation:"am-fade",prefixClass:"alert",placement:null,template:"alert/alert.tpl.html",container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=["$modal","$timeout",function(e,n){function a(a){var r={},i=angular.extend({},t,a);r=e(i),r.$scope.dismissable=!!i.dismissable,i.type&&(r.$scope.type=i.type);var o=r.show;return i.duration&&(r.show=function(){o(),n(function(){r.hide()},1e3*i.duration)}),r}return a}]}).directive("bsAlert",["$window","$location","$sce","$alert",function(t,e,n,a){t.requestAnimationFrame||t.setTimeout;return{restrict:"EAC",scope:!0,link:function(t,e,r){var i={scope:t,element:e,show:!1};angular.forEach(["template","placement","keyboard","html","container","animation","duration","dismissable"],function(t){angular.isDefined(r[t])&&(i[t]=r[t])}),angular.forEach(["title","content","type"],function(e){r[e]&&r.$observe(e,function(a){t[e]=n.trustAsHtml(a)})}),r.bsAlert&&t.$watch(r.bsAlert,function(e){angular.isObject(e)?angular.extend(t,e):t.content=e},!0);var o=a(i);e.on(r.trigger||"click",o.toggle),t.$on("$destroy",function(){o.destroy(),i=null,o=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.alert').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('alert/alert.tpl.html', '<div class="alert" tabindex="-1" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">×</button> <strong ng-bind="title"></strong> <span ng-bind-html="content"></span></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.alert").run(["$templateCache",function(t){t.put("alert/alert.tpl.html",'<div class="alert" tabindex="-1" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">×</button> <strong ng-bind="title"></strong> <span ng-bind-html="content"></span></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal']).provider('$aside', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade-and-slide-right', |
| | | prefixClass: 'aside', |
| | | placement: 'right', |
| | | template: 'aside/aside.tpl.html', |
| | | contentTemplate: false, |
| | | container: false, |
| | | element: null, |
| | | backdrop: true, |
| | | keyboard: true, |
| | | html: false, |
| | | show: true |
| | | }; |
| | | this.$get = [ |
| | | '$modal', |
| | | function ($modal) { |
| | | function AsideFactory(config) { |
| | | var $aside = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $aside = $modal(options); |
| | | return $aside; |
| | | } |
| | | return AsideFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsAside', [ |
| | | '$window', |
| | | '$sce', |
| | | '$aside', |
| | | function ($window, $sce, $aside) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'backdrop', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsAside && scope.$watch(attr.bsAside, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize aside |
| | | var aside = $aside(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', aside.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | aside.destroy(); |
| | | options = null; |
| | | aside = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.aside",["mgcrea.ngStrap.modal"]).provider("$aside",function(){var e=this.defaults={animation:"am-fade-and-slide-right",prefixClass:"aside",placement:"right",template:"aside/aside.tpl.html",contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=["$modal",function(t){function n(n){var a={},i=angular.extend({},e,n);return a=t(i)}return n}]}).directive("bsAside",["$window","$sce","$aside",function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:"EAC",scope:!0,link:function(e,a,i){var r={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),angular.forEach(["title","content"],function(n){i[n]&&i.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),i.bsAside&&e.$watch(i.bsAside,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var o=n(r);a.on(i.trigger||"click",o.toggle),e.$on("$destroy",function(){o.destroy(),r=null,o=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.aside').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('aside/aside.tpl.html', '<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.aside").run(["$templateCache",function(t){t.put("aside/aside.tpl.html",'<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.button', []).provider('$button', function () { |
| | | var defaults = this.defaults = { |
| | | activeClass: 'active', |
| | | toggleEvent: 'click' |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsCheckboxGroup', function () { |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | compile: function postLink(element, attr) { |
| | | element.attr('data-toggle', 'buttons'); |
| | | element.removeAttr('ng-model'); |
| | | var children = element[0].querySelectorAll('input[type="checkbox"]'); |
| | | angular.forEach(children, function (child) { |
| | | var childEl = angular.element(child); |
| | | childEl.attr('bs-checkbox', ''); |
| | | childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value')); |
| | | }); |
| | | } |
| | | }; |
| | | }).directive('bsCheckbox', [ |
| | | '$button', |
| | | '$$rAF', |
| | | function ($button, $$rAF) { |
| | | var defaults = $button.defaults; |
| | | var constantValueRegExp = /^(true|false|\d+)$/; |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | var options = defaults; |
| | | // Support label > input[type="checkbox"] |
| | | var isInput = element[0].nodeName === 'INPUT'; |
| | | var activeElement = isInput ? element.parent() : element; |
| | | var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true; |
| | | if (constantValueRegExp.test(attr.trueValue)) { |
| | | trueValue = scope.$eval(attr.trueValue); |
| | | } |
| | | var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false; |
| | | if (constantValueRegExp.test(attr.falseValue)) { |
| | | falseValue = scope.$eval(attr.falseValue); |
| | | } |
| | | // Parse exotic values |
| | | var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean'; |
| | | if (hasExoticValues) { |
| | | controller.$parsers.push(function (viewValue) { |
| | | // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue); |
| | | return viewValue ? trueValue : falseValue; |
| | | }); |
| | | // Fix rendering for exotic values |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | controller.$render(); |
| | | }); |
| | | } |
| | | // model -> view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var isActive = angular.equals(controller.$modelValue, trueValue); |
| | | $$rAF(function () { |
| | | if (isInput) |
| | | element[0].checked = isActive; |
| | | activeElement.toggleClass(options.activeClass, isActive); |
| | | }); |
| | | }; |
| | | // view -> model |
| | | element.bind(options.toggleEvent, function () { |
| | | scope.$apply(function () { |
| | | // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue); |
| | | if (!isInput) { |
| | | controller.$setViewValue(!activeElement.hasClass('active')); |
| | | } |
| | | if (!hasExoticValues) { |
| | | controller.$render(); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsRadioGroup', function () { |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | compile: function postLink(element, attr) { |
| | | element.attr('data-toggle', 'buttons'); |
| | | element.removeAttr('ng-model'); |
| | | var children = element[0].querySelectorAll('input[type="radio"]'); |
| | | angular.forEach(children, function (child) { |
| | | angular.element(child).attr('bs-radio', ''); |
| | | angular.element(child).attr('ng-model', attr.ngModel); |
| | | }); |
| | | } |
| | | }; |
| | | }).directive('bsRadio', [ |
| | | '$button', |
| | | '$$rAF', |
| | | function ($button, $$rAF) { |
| | | var defaults = $button.defaults; |
| | | var constantValueRegExp = /^(true|false|\d+)$/; |
| | | return { |
| | | restrict: 'A', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | var options = defaults; |
| | | // Support `label > input[type="radio"]` markup |
| | | var isInput = element[0].nodeName === 'INPUT'; |
| | | var activeElement = isInput ? element.parent() : element; |
| | | var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value; |
| | | // model -> view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var isActive = angular.equals(controller.$modelValue, value); |
| | | $$rAF(function () { |
| | | if (isInput) |
| | | element[0].checked = isActive; |
| | | activeElement.toggleClass(options.activeClass, isActive); |
| | | }); |
| | | }; |
| | | // view -> model |
| | | element.bind(options.toggleEvent, function () { |
| | | scope.$apply(function () { |
| | | // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue); |
| | | controller.$setViewValue(value); |
| | | controller.$render(); |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.button",[]).provider("$button",function(){var e=this.defaults={activeClass:"active",toggleEvent:"click"};this.$get=function(){return{defaults:e}}}).directive("bsCheckboxGroup",function(){return{restrict:"A",require:"ngModel",compile:function(e,t){e.attr("data-toggle","buttons"),e.removeAttr("ng-model");var a=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(a,function(e){var a=angular.element(e);a.attr("bs-checkbox",""),a.attr("ng-model",t.ngModel+"."+a.attr("value"))})}}}).directive("bsCheckbox",["$button","$$rAF",function(e,t){var a=e.defaults,n=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(e,r,l,u){var o=a,i="INPUT"===r[0].nodeName,c=i?r.parent():r,s=angular.isDefined(l.trueValue)?l.trueValue:!0;n.test(l.trueValue)&&(s=e.$eval(l.trueValue));var d=angular.isDefined(l.falseValue)?l.falseValue:!1;n.test(l.falseValue)&&(d=e.$eval(l.falseValue));var f="boolean"!=typeof s||"boolean"!=typeof d;f&&(u.$parsers.push(function(e){return e?s:d}),e.$watch(l.ngModel,function(){u.$render()})),u.$render=function(){var e=angular.equals(u.$modelValue,s);t(function(){i&&(r[0].checked=e),c.toggleClass(o.activeClass,e)})},r.bind(o.toggleEvent,function(){e.$apply(function(){i||u.$setViewValue(!c.hasClass("active")),f||u.$render()})})}}}]).directive("bsRadioGroup",function(){return{restrict:"A",require:"ngModel",compile:function(e,t){e.attr("data-toggle","buttons"),e.removeAttr("ng-model");var a=e[0].querySelectorAll('input[type="radio"]');angular.forEach(a,function(e){angular.element(e).attr("bs-radio",""),angular.element(e).attr("ng-model",t.ngModel)})}}}).directive("bsRadio",["$button","$$rAF",function(e,t){var a=e.defaults,n=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(e,r,l,u){var o=a,i="INPUT"===r[0].nodeName,c=i?r.parent():r,s=n.test(l.value)?e.$eval(l.value):l.value;u.$render=function(){var e=angular.equals(u.$modelValue,s);t(function(){i&&(r[0].checked=e),c.toggleClass(o.activeClass,e)})},r.bind(o.toggleEvent,function(){e.$apply(function(){u.$setViewValue(s),u.$render()})})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.helpers.dateParser', []).provider('$dateParser', [ |
| | | '$localeProvider', |
| | | function ($localeProvider) { |
| | | var proto = Date.prototype; |
| | | function isNumeric(n) { |
| | | return !isNaN(parseFloat(n)) && isFinite(n); |
| | | } |
| | | var defaults = this.defaults = { |
| | | format: 'shortDate', |
| | | strict: false |
| | | }; |
| | | this.$get = [ |
| | | '$locale', |
| | | function ($locale) { |
| | | var DateParserFactory = function (config) { |
| | | var options = angular.extend({}, defaults, config); |
| | | var $dateParser = {}; |
| | | var regExpMap = { |
| | | 'sss': '[0-9]{3}', |
| | | 'ss': '[0-5][0-9]', |
| | | 's': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
| | | 'mm': '[0-5][0-9]', |
| | | 'm': options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]', |
| | | 'HH': '[01][0-9]|2[0-3]', |
| | | 'H': options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]', |
| | | 'hh': '[0][1-9]|[1][012]', |
| | | 'h': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
| | | 'a': 'AM|PM', |
| | | 'EEEE': $locale.DATETIME_FORMATS.DAY.join('|'), |
| | | 'EEE': $locale.DATETIME_FORMATS.SHORTDAY.join('|'), |
| | | 'dd': '0[1-9]|[12][0-9]|3[01]', |
| | | 'd': options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]', |
| | | 'MMMM': $locale.DATETIME_FORMATS.MONTH.join('|'), |
| | | 'MMM': $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), |
| | | 'MM': '0[1-9]|1[012]', |
| | | 'M': options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]', |
| | | 'yyyy': '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}', |
| | | 'yy': '[0-9]{2}', |
| | | 'y': options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}' |
| | | }; |
| | | var setFnMap = { |
| | | 'sss': proto.setMilliseconds, |
| | | 'ss': proto.setSeconds, |
| | | 's': proto.setSeconds, |
| | | 'mm': proto.setMinutes, |
| | | 'm': proto.setMinutes, |
| | | 'HH': proto.setHours, |
| | | 'H': proto.setHours, |
| | | 'hh': proto.setHours, |
| | | 'h': proto.setHours, |
| | | 'dd': proto.setDate, |
| | | 'd': proto.setDate, |
| | | 'a': function (value) { |
| | | var hours = this.getHours(); |
| | | return this.setHours(value.match(/pm/i) ? hours + 12 : hours); |
| | | }, |
| | | 'MMMM': function (value) { |
| | | return this.setMonth($locale.DATETIME_FORMATS.MONTH.indexOf(value)); |
| | | }, |
| | | 'MMM': function (value) { |
| | | return this.setMonth($locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value)); |
| | | }, |
| | | 'MM': function (value) { |
| | | return this.setMonth(1 * value - 1); |
| | | }, |
| | | 'M': function (value) { |
| | | return this.setMonth(1 * value - 1); |
| | | }, |
| | | 'yyyy': proto.setFullYear, |
| | | 'yy': function (value) { |
| | | return this.setFullYear(2000 + 1 * value); |
| | | }, |
| | | 'y': proto.setFullYear |
| | | }; |
| | | var regex, setMap; |
| | | $dateParser.init = function () { |
| | | $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format; |
| | | regex = regExpForFormat($dateParser.$format); |
| | | setMap = setMapForFormat($dateParser.$format); |
| | | }; |
| | | $dateParser.isValid = function (date) { |
| | | if (angular.isDate(date)) |
| | | return !isNaN(date.getTime()); |
| | | return regex.test(date); |
| | | }; |
| | | $dateParser.parse = function (value, baseDate, format) { |
| | | var formatRegex = format ? regExpForFormat(format) : regex; |
| | | var formatSetMap = format ? setMapForFormat(format) : setMap; |
| | | if (angular.isDate(value)) |
| | | return value; |
| | | var matches = formatRegex.exec(value); |
| | | if (!matches) |
| | | return false; |
| | | var date = baseDate || new Date(0, 0, 1); |
| | | for (var i = 0; i < matches.length - 1; i++) { |
| | | formatSetMap[i] && formatSetMap[i].call(date, matches[i + 1]); |
| | | } |
| | | return date; |
| | | }; |
| | | // Private functions |
| | | function setMapForFormat(format) { |
| | | var keys = Object.keys(setFnMap), i; |
| | | var map = [], sortedMap = []; |
| | | // Map to setFn |
| | | var clonedFormat = format; |
| | | for (i = 0; i < keys.length; i++) { |
| | | if (format.split(keys[i]).length > 1) { |
| | | var index = clonedFormat.search(keys[i]); |
| | | format = format.split(keys[i]).join(''); |
| | | if (setFnMap[keys[i]]) |
| | | map[index] = setFnMap[keys[i]]; |
| | | } |
| | | } |
| | | // Sort result map |
| | | angular.forEach(map, function (v) { |
| | | sortedMap.push(v); |
| | | }); |
| | | return sortedMap; |
| | | } |
| | | function escapeReservedSymbols(text) { |
| | | return text.replace(/\//g, '[\\/]').replace('/-/g', '[-]').replace(/\./g, '[.]').replace(/\\s/g, '[\\s]'); |
| | | } |
| | | function regExpForFormat(format) { |
| | | var keys = Object.keys(regExpMap), i; |
| | | var re = format; |
| | | // Abstract replaces to avoid collisions |
| | | for (i = 0; i < keys.length; i++) { |
| | | re = re.split(keys[i]).join('${' + i + '}'); |
| | | } |
| | | // Replace abstracted values |
| | | for (i = 0; i < keys.length; i++) { |
| | | re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')'); |
| | | } |
| | | format = escapeReservedSymbols(format); |
| | | return new RegExp('^' + re + '$', ['i']); |
| | | } |
| | | $dateParser.init(); |
| | | return $dateParser; |
| | | }; |
| | | return DateParserFactory; |
| | | } |
| | | ]; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.helpers.dateParser",[]).provider("$dateParser",["$localeProvider",function(){var t=Date.prototype,e=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale",function(r){var s=function(s){function n(t){var e,r=Object.keys(f),s=[],n=[],i=t;for(e=0;e<r.length;e++)if(t.split(r[e]).length>1){var a=i.search(r[e]);t=t.split(r[e]).join(""),f[r[e]]&&(s[a]=f[r[e]])}return angular.forEach(s,function(t){n.push(t)}),n}function i(t){return t.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function a(t){var e,r=Object.keys(l),s=t;for(e=0;e<r.length;e++)s=s.split(r[e]).join("${"+e+"}");for(e=0;e<r.length;e++)s=s.split("${"+e+"}").join("("+l[r[e]]+")");return t=i(t),new RegExp("^"+s+"$",["i"])}var o,u,M=angular.extend({},e,s),c={},l={sss:"[0-9]{3}",ss:"[0-5][0-9]",s:M.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",mm:"[0-5][0-9]",m:M.strict?"[1-5]?[0-9]":"[0-9]|[0-5][0-9]",HH:"[01][0-9]|2[0-3]",H:M.strict?"1?[0-9]|2[0-3]":"[01]?[0-9]|2[0-3]",hh:"[0][1-9]|[1][012]",h:M.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",a:"AM|PM",EEEE:r.DATETIME_FORMATS.DAY.join("|"),EEE:r.DATETIME_FORMATS.SHORTDAY.join("|"),dd:"0[1-9]|[12][0-9]|3[01]",d:M.strict?"[1-9]|[1-2][0-9]|3[01]":"0?[1-9]|[1-2][0-9]|3[01]",MMMM:r.DATETIME_FORMATS.MONTH.join("|"),MMM:r.DATETIME_FORMATS.SHORTMONTH.join("|"),MM:"0[1-9]|1[012]",M:M.strict?"[1-9]|1[012]":"0?[1-9]|1[012]",yyyy:"[1]{1}[0-9]{3}|[2]{1}[0-9]{3}",yy:"[0-9]{2}",y:M.strict?"-?(0|[1-9][0-9]{0,3})":"-?0*[0-9]{1,4}"},f={sss:t.setMilliseconds,ss:t.setSeconds,s:t.setSeconds,mm:t.setMinutes,m:t.setMinutes,HH:t.setHours,H:t.setHours,hh:t.setHours,h:t.setHours,dd:t.setDate,d:t.setDate,a:function(t){var e=this.getHours();return this.setHours(t.match(/pm/i)?e+12:e)},MMMM:function(t){return this.setMonth(r.DATETIME_FORMATS.MONTH.indexOf(t))},MMM:function(t){return this.setMonth(r.DATETIME_FORMATS.SHORTMONTH.indexOf(t))},MM:function(t){return this.setMonth(1*t-1)},M:function(t){return this.setMonth(1*t-1)},yyyy:t.setFullYear,yy:function(t){return this.setFullYear(2e3+1*t)},y:t.setFullYear};return c.init=function(){c.$format=r.DATETIME_FORMATS[M.format]||M.format,o=a(c.$format),u=n(c.$format)},c.isValid=function(t){return angular.isDate(t)?!isNaN(t.getTime()):o.test(t)},c.parse=function(t,e,r){var s=r?a(r):o,i=r?n(r):u;if(angular.isDate(t))return t;var M=s.exec(t);if(!M)return!1;for(var c=e||new Date(0,0,1),l=0;l<M.length-1;l++)i[l]&&i[l].call(c,M[l+1]);return c},c.init(),c};return s}]}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.datepicker', [ |
| | | 'mgcrea.ngStrap.helpers.dateParser', |
| | | 'mgcrea.ngStrap.tooltip' |
| | | ]).provider('$datepicker', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'datepicker', |
| | | placement: 'bottom-left', |
| | | template: 'datepicker/datepicker.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | useNative: false, |
| | | dateType: 'date', |
| | | dateFormat: 'shortDate', |
| | | modelDateFormat: null, |
| | | dayFormat: 'dd', |
| | | strictFormat: false, |
| | | autoclose: false, |
| | | minDate: -Infinity, |
| | | maxDate: +Infinity, |
| | | startView: 0, |
| | | minView: 0, |
| | | startWeek: 0, |
| | | iconLeft: 'glyphicon glyphicon-chevron-left', |
| | | iconRight: 'glyphicon glyphicon-chevron-right' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$sce', |
| | | '$locale', |
| | | 'dateFilter', |
| | | 'datepickerViews', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $sce, $locale, dateFilter, datepickerViews, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | if (!defaults.lang) |
| | | defaults.lang = $locale.id; |
| | | function DatepickerFactory(element, controller, config) { |
| | | var $datepicker = $tooltip(element, angular.extend({}, defaults, config)); |
| | | var parentScope = config.scope; |
| | | var options = $datepicker.$options; |
| | | var scope = $datepicker.$scope; |
| | | if (options.startView) |
| | | options.startView -= options.minView; |
| | | // View vars |
| | | var pickerViews = datepickerViews($datepicker); |
| | | $datepicker.$views = pickerViews.views; |
| | | var viewDate = pickerViews.viewDate; |
| | | scope.$mode = options.startView; |
| | | scope.$iconLeft = options.iconLeft; |
| | | scope.$iconRight = options.iconRight; |
| | | var $picker = $datepicker.$views[scope.$mode]; |
| | | // Scope methods |
| | | scope.$select = function (date) { |
| | | $datepicker.select(date); |
| | | }; |
| | | scope.$selectPane = function (value) { |
| | | $datepicker.$selectPane(value); |
| | | }; |
| | | scope.$toggleMode = function () { |
| | | $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length); |
| | | }; |
| | | // Public methods |
| | | $datepicker.update = function (date) { |
| | | // console.warn('$datepicker.update() newValue=%o', date); |
| | | if (angular.isDate(date) && !isNaN(date.getTime())) { |
| | | $datepicker.$date = date; |
| | | $picker.update.call($picker, date); |
| | | } |
| | | // Build only if pristine |
| | | $datepicker.$build(true); |
| | | }; |
| | | $datepicker.select = function (date, keep) { |
| | | // console.warn('$datepicker.select', date, scope.$mode); |
| | | if (!angular.isDate(controller.$dateValue)) |
| | | controller.$dateValue = new Date(date); |
| | | controller.$dateValue.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); |
| | | if (!scope.$mode || keep) { |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | if (options.autoclose && !keep) { |
| | | $datepicker.hide(true); |
| | | } |
| | | } else { |
| | | angular.extend(viewDate, { |
| | | year: date.getFullYear(), |
| | | month: date.getMonth(), |
| | | date: date.getDate() |
| | | }); |
| | | $datepicker.setMode(scope.$mode - 1); |
| | | $datepicker.$build(); |
| | | } |
| | | }; |
| | | $datepicker.setMode = function (mode) { |
| | | // console.warn('$datepicker.setMode', mode); |
| | | scope.$mode = mode; |
| | | $picker = $datepicker.$views[scope.$mode]; |
| | | $datepicker.$build(); |
| | | }; |
| | | // Protected methods |
| | | $datepicker.$build = function (pristine) { |
| | | // console.warn('$datepicker.$build() viewDate=%o', viewDate); |
| | | if (pristine === true && $picker.built) |
| | | return; |
| | | if (pristine === false && !$picker.built) |
| | | return; |
| | | $picker.build.call($picker); |
| | | }; |
| | | $datepicker.$updateSelected = function () { |
| | | for (var i = 0, l = scope.rows.length; i < l; i++) { |
| | | angular.forEach(scope.rows[i], updateSelected); |
| | | } |
| | | }; |
| | | $datepicker.$isSelected = function (date) { |
| | | return $picker.isSelected(date); |
| | | }; |
| | | $datepicker.$selectPane = function (value) { |
| | | var steps = $picker.steps; |
| | | var targetDate = new Date(Date.UTC(viewDate.year + (steps.year || 0) * value, viewDate.month + (steps.month || 0) * value, viewDate.date + (steps.day || 0) * value)); |
| | | angular.extend(viewDate, { |
| | | year: targetDate.getUTCFullYear(), |
| | | month: targetDate.getUTCMonth(), |
| | | date: targetDate.getUTCDate() |
| | | }); |
| | | $datepicker.$build(); |
| | | }; |
| | | $datepicker.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | if (targetEl[0].nodeName.toLowerCase() !== 'button') { |
| | | targetEl = targetEl.parent(); |
| | | } |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $datepicker.$onKeyDown = function (evt) { |
| | | if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | if (evt.keyCode === 13) { |
| | | if (!scope.$mode) { |
| | | return $datepicker.hide(true); |
| | | } else { |
| | | return scope.$apply(function () { |
| | | $datepicker.setMode(scope.$mode - 1); |
| | | }); |
| | | } |
| | | } |
| | | // Navigate with keyboard |
| | | $picker.onKeyDown(evt); |
| | | parentScope.$digest(); |
| | | }; |
| | | // Private |
| | | function updateSelected(el) { |
| | | el.selected = $datepicker.$isSelected(el.date); |
| | | } |
| | | function focusElement() { |
| | | element[0].focus(); |
| | | } |
| | | // Overrides |
| | | var _init = $datepicker.init; |
| | | $datepicker.init = function () { |
| | | if (isNative && options.useNative) { |
| | | element.prop('type', 'date'); |
| | | element.css('-webkit-appearance', 'textfield'); |
| | | return; |
| | | } else if (isTouch) { |
| | | element.prop('type', 'text'); |
| | | element.attr('readonly', 'true'); |
| | | element.on('click', focusElement); |
| | | } |
| | | _init(); |
| | | }; |
| | | var _destroy = $datepicker.destroy; |
| | | $datepicker.destroy = function () { |
| | | if (isNative && options.useNative) { |
| | | element.off('click', focusElement); |
| | | } |
| | | _destroy(); |
| | | }; |
| | | var _show = $datepicker.show; |
| | | $datepicker.show = function () { |
| | | _show(); |
| | | setTimeout(function () { |
| | | $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $datepicker.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $datepicker.hide; |
| | | $datepicker.hide = function (blur) { |
| | | $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $datepicker.$onKeyDown); |
| | | } |
| | | _hide(blur); |
| | | }; |
| | | return $datepicker; |
| | | } |
| | | DatepickerFactory.defaults = defaults; |
| | | return DatepickerFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsDatepicker', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$datepicker', |
| | | '$dateParser', |
| | | '$timeout', |
| | | function ($window, $parse, $q, $locale, dateFilter, $datepicker, $dateParser, $timeout) { |
| | | var defaults = $datepicker.defaults; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | var isNumeric = function (n) { |
| | | return !isNaN(parseFloat(n)) && isFinite(n); |
| | | }; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | controller: controller |
| | | }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'autoclose', |
| | | 'dateType', |
| | | 'dateFormat', |
| | | 'modelDateFormat', |
| | | 'dayFormat', |
| | | 'strictFormat', |
| | | 'startWeek', |
| | | 'useNative', |
| | | 'lang', |
| | | 'startView', |
| | | 'minView' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Initialize datepicker |
| | | if (isNative && options.useNative) |
| | | options.dateFormat = 'yyyy-MM-dd'; |
| | | var datepicker = $datepicker(element, controller, options); |
| | | options = datepicker.$options; |
| | | // Observe attributes for changes |
| | | angular.forEach([ |
| | | 'minDate', |
| | | 'maxDate' |
| | | ], function (key) { |
| | | // console.warn('attr.$observe(%s)', key, attr[key]); |
| | | angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) { |
| | | // console.warn('attr.$observe(%s)=%o', key, newValue); |
| | | if (newValue === 'today') { |
| | | var today = new Date(); |
| | | datepicker.$options[key] = +new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, key === 'minDate' ? 0 : -1); |
| | | } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) { |
| | | // Support {{ dateObj }} |
| | | datepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2)); |
| | | } else if (isNumeric(newValue)) { |
| | | datepicker.$options[key] = +new Date(parseInt(newValue, 10)); |
| | | } else { |
| | | datepicker.$options[key] = +new Date(newValue); |
| | | } |
| | | // Build only if dirty |
| | | !isNaN(datepicker.$options[key]) && datepicker.$build(false); |
| | | }); |
| | | }); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | datepicker.update(controller.$dateValue); |
| | | }, true); |
| | | var dateParser = $dateParser({ |
| | | format: options.dateFormat, |
| | | lang: options.lang, |
| | | strict: options.strictFormat |
| | | }); |
| | | // viewValue -> $parsers -> modelValue |
| | | controller.$parsers.unshift(function (viewValue) { |
| | | // console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue); |
| | | // Null values should correctly reset the model value & validity |
| | | if (!viewValue) { |
| | | controller.$setValidity('date', true); |
| | | return; |
| | | } |
| | | var parsedDate = dateParser.parse(viewValue, controller.$dateValue); |
| | | if (!parsedDate || isNaN(parsedDate.getTime())) { |
| | | controller.$setValidity('date', false); |
| | | return; |
| | | } else { |
| | | var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate; |
| | | var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate; |
| | | var isValid = isMinValid && isMaxValid; |
| | | controller.$setValidity('date', isValid); |
| | | controller.$setValidity('min', isMinValid); |
| | | controller.$setValidity('max', isMaxValid); |
| | | // Only update the model when we have a valid date |
| | | if (isValid) |
| | | controller.$dateValue = parsedDate; |
| | | } |
| | | if (options.dateType === 'string') { |
| | | return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat); |
| | | } else if (options.dateType === 'number') { |
| | | return controller.$dateValue.getTime(); |
| | | } else if (options.dateType === 'iso') { |
| | | return controller.$dateValue.toISOString(); |
| | | } else { |
| | | return new Date(controller.$dateValue); |
| | | } |
| | | }); |
| | | // modelValue -> $formatters -> viewValue |
| | | controller.$formatters.push(function (modelValue) { |
| | | // console.warn('$formatter("%s"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue); |
| | | var date; |
| | | if (angular.isUndefined(modelValue) || modelValue === null) { |
| | | date = NaN; |
| | | } else if (angular.isDate(modelValue)) { |
| | | date = modelValue; |
| | | } else if (options.dateType === 'string') { |
| | | date = dateParser.parse(modelValue, null, options.modelDateFormat); |
| | | } else { |
| | | date = new Date(modelValue); |
| | | } |
| | | // Setup default value? |
| | | // if(isNaN(date.getTime())) { |
| | | // var today = new Date(); |
| | | // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0); |
| | | // } |
| | | controller.$dateValue = date; |
| | | return controller.$dateValue; |
| | | }); |
| | | // viewValue -> element |
| | | controller.$render = function () { |
| | | // console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue); |
| | | element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.dateFormat)); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | datepicker.destroy(); |
| | | options = null; |
| | | datepicker = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).provider('datepickerViews', function () { |
| | | var defaults = this.defaults = { |
| | | dayFormat: 'dd', |
| | | daySplit: 7 |
| | | }; |
| | | // Split array into smaller arrays |
| | | function split(arr, size) { |
| | | var arrays = []; |
| | | while (arr.length > 0) { |
| | | arrays.push(arr.splice(0, size)); |
| | | } |
| | | return arrays; |
| | | } |
| | | // Modulus operator |
| | | function mod(n, m) { |
| | | return (n % m + m) % m; |
| | | } |
| | | this.$get = [ |
| | | '$locale', |
| | | '$sce', |
| | | 'dateFilter', |
| | | function ($locale, $sce, dateFilter) { |
| | | return function (picker) { |
| | | var scope = picker.$scope; |
| | | var options = picker.$options; |
| | | var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY; |
| | | var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek)); |
| | | var weekDaysLabelsHtml = $sce.trustAsHtml('<th class="dow text-center">' + weekDaysLabels.join('</th><th class="dow text-center">') + '</th>'); |
| | | var startDate = picker.$date || new Date(); |
| | | var viewDate = { |
| | | year: startDate.getFullYear(), |
| | | month: startDate.getMonth(), |
| | | date: startDate.getDate() |
| | | }; |
| | | var timezoneOffset = startDate.getTimezoneOffset() * 60000; |
| | | var views = [ |
| | | { |
| | | format: options.dayFormat, |
| | | split: 7, |
| | | steps: { month: 1 }, |
| | | update: function (date, force) { |
| | | if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getDate() !== viewDate.date) { |
| | | viewDate.date = picker.$date.getDate(); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset(); |
| | | var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 86400000), firstDateOffset = firstDate.getTimezoneOffset(); |
| | | // Handle daylight time switch |
| | | if (firstDateOffset !== firstDayOfMonthOffset) |
| | | firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60000); |
| | | var days = [], day; |
| | | for (var i = 0; i < 42; i++) { |
| | | // < 7 * 6 |
| | | day = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i); |
| | | days.push({ |
| | | date: day, |
| | | label: dateFilter(day, this.format), |
| | | selected: picker.$date && this.isSelected(day), |
| | | muted: day.getMonth() !== viewDate.month, |
| | | disabled: this.isDisabled(day) |
| | | }); |
| | | } |
| | | scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy'); |
| | | scope.showLabels = true; |
| | | scope.labels = weekDaysLabelsHtml; |
| | | scope.rows = split(days, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | return date.getTime() < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualTime = picker.$date.getTime(); |
| | | var newDate; |
| | | if (evt.keyCode === 37) |
| | | newDate = new Date(actualTime - 1 * 86400000); |
| | | else if (evt.keyCode === 38) |
| | | newDate = new Date(actualTime - 7 * 86400000); |
| | | else if (evt.keyCode === 39) |
| | | newDate = new Date(actualTime + 1 * 86400000); |
| | | else if (evt.keyCode === 40) |
| | | newDate = new Date(actualTime + 7 * 86400000); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | }, |
| | | { |
| | | name: 'month', |
| | | format: 'MMM', |
| | | split: 4, |
| | | steps: { year: 1 }, |
| | | update: function (date, force) { |
| | | if (!this.built || date.getFullYear() !== viewDate.year) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getMonth() !== viewDate.month) { |
| | | angular.extend(viewDate, { |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstMonth = new Date(viewDate.year, 0, 1); |
| | | var months = [], month; |
| | | for (var i = 0; i < 12; i++) { |
| | | month = new Date(viewDate.year, i, 1); |
| | | months.push({ |
| | | date: month, |
| | | label: dateFilter(month, this.format), |
| | | selected: picker.$isSelected(month), |
| | | disabled: this.isDisabled(month) |
| | | }); |
| | | } |
| | | scope.title = dateFilter(month, 'yyyy'); |
| | | scope.showLabels = false; |
| | | scope.rows = split(months, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0); |
| | | return lastDate < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualMonth = picker.$date.getMonth(); |
| | | var newDate = new Date(picker.$date); |
| | | if (evt.keyCode === 37) |
| | | newDate.setMonth(actualMonth - 1); |
| | | else if (evt.keyCode === 38) |
| | | newDate.setMonth(actualMonth - 4); |
| | | else if (evt.keyCode === 39) |
| | | newDate.setMonth(actualMonth + 1); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setMonth(actualMonth + 4); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | }, |
| | | { |
| | | name: 'year', |
| | | format: 'yyyy', |
| | | split: 4, |
| | | steps: { year: 12 }, |
| | | update: function (date, force) { |
| | | if (!this.built || force || parseInt(date.getFullYear() / 20, 10) !== parseInt(viewDate.year / 20, 10)) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$build(); |
| | | } else if (date.getFullYear() !== viewDate.year) { |
| | | angular.extend(viewDate, { |
| | | year: picker.$date.getFullYear(), |
| | | month: picker.$date.getMonth(), |
| | | date: picker.$date.getDate() |
| | | }); |
| | | picker.$updateSelected(); |
| | | } |
| | | }, |
| | | build: function () { |
| | | var firstYear = viewDate.year - viewDate.year % (this.split * 3); |
| | | var years = [], year; |
| | | for (var i = 0; i < 12; i++) { |
| | | year = new Date(firstYear + i, 0, 1); |
| | | years.push({ |
| | | date: year, |
| | | label: dateFilter(year, this.format), |
| | | selected: picker.$isSelected(year), |
| | | disabled: this.isDisabled(year) |
| | | }); |
| | | } |
| | | scope.title = years[0].label + '-' + years[years.length - 1].label; |
| | | scope.showLabels = false; |
| | | scope.rows = split(years, this.split); |
| | | this.built = true; |
| | | }, |
| | | isSelected: function (date) { |
| | | return picker.$date && date.getFullYear() === picker.$date.getFullYear(); |
| | | }, |
| | | isDisabled: function (date) { |
| | | var lastDate = +new Date(date.getFullYear() + 1, 0, 0); |
| | | return lastDate < options.minDate || date.getTime() > options.maxDate; |
| | | }, |
| | | onKeyDown: function (evt) { |
| | | var actualYear = picker.$date.getFullYear(), newDate = new Date(picker.$date); |
| | | if (evt.keyCode === 37) |
| | | newDate.setYear(actualYear - 1); |
| | | else if (evt.keyCode === 38) |
| | | newDate.setYear(actualYear - 4); |
| | | else if (evt.keyCode === 39) |
| | | newDate.setYear(actualYear + 1); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setYear(actualYear + 4); |
| | | if (!this.isDisabled(newDate)) |
| | | picker.select(newDate, true); |
| | | } |
| | | } |
| | | ]; |
| | | return { |
| | | views: options.minView ? Array.prototype.slice.call(views, options.minView) : views, |
| | | viewDate: viewDate |
| | | }; |
| | | }; |
| | | } |
| | | ]; |
| | | }); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.datepicker",["mgcrea.ngStrap.helpers.dateParser","mgcrea.ngStrap.tooltip"]).provider("$datepicker",function(){var e=this.defaults={animation:"am-fade",prefixClass:"datepicker",placement:"bottom-left",template:"datepicker/datepicker.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,useNative:!1,dateType:"date",dateFormat:"shortDate",modelDateFormat:null,dayFormat:"dd",strictFormat:!1,autoclose:!1,minDate:-1/0,maxDate:+1/0,startView:0,minView:0,startWeek:0,iconLeft:"glyphicon glyphicon-chevron-left",iconRight:"glyphicon glyphicon-chevron-right"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","datepickerViews","$tooltip",function(t,a,n,i,o,r,l,d){function s(t,a,n){function i(e){e.selected=r.$isSelected(e.date)}function o(){t[0].focus()}var r=d(t,angular.extend({},e,n)),s=n.scope,g=r.$options,$=r.$scope;g.startView&&(g.startView-=g.minView);var m=l(r);r.$views=m.views;var h=m.viewDate;$.$mode=g.startView,$.$iconLeft=g.iconLeft,$.$iconRight=g.iconRight;var f=r.$views[$.$mode];$.$select=function(e){r.select(e)},$.$selectPane=function(e){r.$selectPane(e)},$.$toggleMode=function(){r.setMode(($.$mode+1)%r.$views.length)},r.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(r.$date=e,f.update.call(f,e)),r.$build(!0)},r.select=function(e,t){angular.isDate(a.$dateValue)||(a.$dateValue=new Date(e)),a.$dateValue.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),!$.$mode||t?(a.$setViewValue(a.$dateValue),a.$render(),g.autoclose&&!t&&r.hide(!0)):(angular.extend(h,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),r.setMode($.$mode-1),r.$build())},r.setMode=function(e){$.$mode=e,f=r.$views[$.$mode],r.$build()},r.$build=function(e){e===!0&&f.built||(e!==!1||f.built)&&f.build.call(f)},r.$updateSelected=function(){for(var e=0,t=$.rows.length;t>e;e++)angular.forEach($.rows[e],i)},r.$isSelected=function(e){return f.isSelected(e)},r.$selectPane=function(e){var t=f.steps,a=new Date(Date.UTC(h.year+(t.year||0)*e,h.month+(t.month||0)*e,h.date+(t.day||0)*e));angular.extend(h,{year:a.getUTCFullYear(),month:a.getUTCMonth(),date:a.getUTCDate()}),r.$build()},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),u){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},r.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return $.$mode?$.$apply(function(){r.setMode($.$mode-1)}):r.hide(!0);f.onKeyDown(e),s.$digest()}};var p=r.init;r.init=function(){return c&&g.useNative?(t.prop("type","date"),void t.css("-webkit-appearance","textfield")):(u&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",o)),void p())};var y=r.destroy;r.destroy=function(){c&&g.useNative&&t.off("click",o),y()};var D=r.show;r.show=function(){D(),setTimeout(function(){r.$element.on(u?"touchstart":"mousedown",r.$onMouseDown),g.keyboard&&t.on("keydown",r.$onKeyDown)})};var w=r.hide;return r.hide=function(e){r.$element.off(u?"touchstart":"mousedown",r.$onMouseDown),g.keyboard&&t.off("keydown",r.$onKeyDown),w(e)},r}var u=(angular.element(t.document.body),"createTouch"in t.document),c=/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent);return e.lang||(e.lang=o.id),s.defaults=e,s}]}).directive("bsDatepicker",["$window","$parse","$q","$locale","dateFilter","$datepicker","$dateParser","$timeout",function(e,t,a,n,i,o,r){var l=(o.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent)),d=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};return{restrict:"EAC",require:"ngModel",link:function(e,t,a,n){var s={scope:e,controller:n};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","useNative","lang","startView","minView"],function(e){angular.isDefined(a[e])&&(s[e]=a[e])}),l&&s.useNative&&(s.dateFormat="yyyy-MM-dd");var u=o(t,n,s);s=u.$options,angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(a[e])&&a.$observe(e,function(t){if("today"===t){var a=new Date;u.$options[e]=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+("maxDate"===e?1:0),0,0,0,"minDate"===e?0:-1)}else u.$options[e]=angular.isString(t)&&t.match(/^".+"$/)?+new Date(t.substr(1,t.length-2)):d(t)?+new Date(parseInt(t,10)):+new Date(t);!isNaN(u.$options[e])&&u.$build(!1)})}),e.$watch(a.ngModel,function(){u.update(n.$dateValue)},!0);var c=r({format:s.dateFormat,lang:s.lang,strict:s.strictFormat});n.$parsers.unshift(function(e){if(!e)return void n.$setValidity("date",!0);var t=c.parse(e,n.$dateValue);if(!t||isNaN(t.getTime()))return void n.$setValidity("date",!1);var a=isNaN(u.$options.minDate)||t.getTime()>=u.$options.minDate,o=isNaN(u.$options.maxDate)||t.getTime()<=u.$options.maxDate,r=a&&o;return n.$setValidity("date",r),n.$setValidity("min",a),n.$setValidity("max",o),r&&(n.$dateValue=t),"string"===s.dateType?i(t,s.modelDateFormat||s.dateFormat):"number"===s.dateType?n.$dateValue.getTime():"iso"===s.dateType?n.$dateValue.toISOString():new Date(n.$dateValue)}),n.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===s.dateType?c.parse(e,null,s.modelDateFormat):new Date(e),n.$dateValue=t,n.$dateValue}),n.$render=function(){t.val(!n.$dateValue||isNaN(n.$dateValue.getTime())?"":i(n.$dateValue,s.dateFormat))},e.$on("$destroy",function(){u.destroy(),s=null,u=null})}}}]).provider("datepickerViews",function(){function e(e,t){for(var a=[];e.length>0;)a.push(e.splice(0,t));return a}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:"dd",daySplit:7};this.$get=["$locale","$sce","dateFilter",function(a,n,i){return function(o){var r=o.$scope,l=o.$options,d=a.DATETIME_FORMATS.SHORTDAY,s=d.slice(l.startWeek).concat(d.slice(0,l.startWeek)),u=n.trustAsHtml('<th class="dow text-center">'+s.join('</th><th class="dow text-center">')+"</th>"),c=o.$date||new Date,g={year:c.getFullYear(),month:c.getMonth(),date:c.getDate()},$=(6e4*c.getTimezoneOffset(),[{format:l.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==g.year||e.getMonth()!==g.month?(angular.extend(g,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build()):e.getDate()!==g.date&&(g.date=o.$date.getDate(),o.$updateSelected())},build:function(){var a=new Date(g.year,g.month,1),n=a.getTimezoneOffset(),d=new Date(+a-864e5*t(a.getDay()-l.startWeek,7)),s=d.getTimezoneOffset();s!==n&&(d=new Date(+d+6e4*(s-n)));for(var c,$=[],m=0;42>m;m++)c=new Date(d.getFullYear(),d.getMonth(),d.getDate()+m),$.push({date:c,label:i(c,this.format),selected:o.$date&&this.isSelected(c),muted:c.getMonth()!==g.month,disabled:this.isDisabled(c)});r.title=i(a,"MMMM yyyy"),r.showLabels=!0,r.labels=u,r.rows=e($,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()&&e.getMonth()===o.$date.getMonth()&&e.getDate()===o.$date.getDate()},isDisabled:function(e){return e.getTime()<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t,a=o.$date.getTime();37===e.keyCode?t=new Date(a-864e5):38===e.keyCode?t=new Date(a-6048e5):39===e.keyCode?t=new Date(a+864e5):40===e.keyCode&&(t=new Date(a+6048e5)),this.isDisabled(t)||o.select(t,!0)}},{name:"month",format:"MMM",split:4,steps:{year:1},update:function(e){this.built&&e.getFullYear()===g.year?e.getMonth()!==g.month&&(angular.extend(g,{month:o.$date.getMonth(),date:o.$date.getDate()}),o.$updateSelected()):(angular.extend(g,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build())},build:function(){for(var t,a=(new Date(g.year,0,1),[]),n=0;12>n;n++)t=new Date(g.year,n,1),a.push({date:t,label:i(t,this.format),selected:o.$isSelected(t),disabled:this.isDisabled(t)});r.title=i(t,"yyyy"),r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()&&e.getMonth()===o.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return t<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t=o.$date.getMonth(),a=new Date(o.$date);37===e.keyCode?a.setMonth(t-1):38===e.keyCode?a.setMonth(t-4):39===e.keyCode?a.setMonth(t+1):40===e.keyCode&&a.setMonth(t+4),this.isDisabled(a)||o.select(a,!0)}},{name:"year",format:"yyyy",split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(g.year/20,10)?(angular.extend(g,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build()):e.getFullYear()!==g.year&&(angular.extend(g,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$updateSelected())},build:function(){for(var t,a=g.year-g.year%(3*this.split),n=[],l=0;12>l;l++)t=new Date(a+l,0,1),n.push({date:t,label:i(t,this.format),selected:o.$isSelected(t),disabled:this.isDisabled(t)});r.title=n[0].label+"-"+n[n.length-1].label,r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return t<l.minDate||e.getTime()>l.maxDate},onKeyDown:function(e){var t=o.$date.getFullYear(),a=new Date(o.$date);37===e.keyCode?a.setYear(t-1):38===e.keyCode?a.setYear(t-4):39===e.keyCode?a.setYear(t+1):40===e.keyCode&&a.setYear(t+4),this.isDisabled(a)||o.select(a,!0)}}]);return{views:l.minView?Array.prototype.slice.call($,l.minView):$,viewDate:g}}}]}); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.datepicker').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('datepicker/datepicker.tpl.html', '<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.datepicker").run(["$templateCache",function(t){t.put("datepicker/datepicker.tpl.html",'<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.helpers.debounce', []).constant('debounce', function (func, wait, immediate) { |
| | | var timeout, args, context, timestamp, result; |
| | | return function () { |
| | | context = this; |
| | | args = arguments; |
| | | timestamp = new Date(); |
| | | var later = function () { |
| | | var last = new Date() - timestamp; |
| | | if (last < wait) { |
| | | timeout = setTimeout(later, wait - last); |
| | | } else { |
| | | timeout = null; |
| | | if (!immediate) |
| | | result = func.apply(context, args); |
| | | } |
| | | }; |
| | | var callNow = immediate && !timeout; |
| | | if (!timeout) { |
| | | timeout = setTimeout(later, wait); |
| | | } |
| | | if (callNow) |
| | | result = func.apply(context, args); |
| | | return result; |
| | | }; |
| | | }).constant('throttle', function (func, wait, options) { |
| | | var context, args, result; |
| | | var timeout = null; |
| | | var previous = 0; |
| | | options || (options = {}); |
| | | var later = function () { |
| | | previous = options.leading === false ? 0 : new Date(); |
| | | timeout = null; |
| | | result = func.apply(context, args); |
| | | }; |
| | | return function () { |
| | | var now = new Date(); |
| | | if (!previous && options.leading === false) |
| | | previous = now; |
| | | var remaining = wait - (now - previous); |
| | | context = this; |
| | | args = arguments; |
| | | if (remaining <= 0) { |
| | | clearTimeout(timeout); |
| | | timeout = null; |
| | | previous = now; |
| | | result = func.apply(context, args); |
| | | } else if (!timeout && options.trailing !== false) { |
| | | timeout = setTimeout(later, remaining); |
| | | } |
| | | return result; |
| | | }; |
| | | }); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.helpers.debounce",[]).constant("debounce",function(n,t,e){var a,r,u,l,i;return function(){u=this,r=arguments,l=new Date;var o=function(){var c=new Date-l;t>c?a=setTimeout(o,t-c):(a=null,e||(i=n.apply(u,r)))},c=e&&!a;return a||(a=setTimeout(o,t)),c&&(i=n.apply(u,r)),i}}).constant("throttle",function(n,t,e){var a,r,u,l=null,i=0;e||(e={});var o=function(){i=e.leading===!1?0:new Date,l=null,u=n.apply(a,r)};return function(){var c=new Date;i||e.leading!==!1||(i=c);var s=t-(c-i);return a=this,r=arguments,0>=s?(clearTimeout(l),l=null,i=c,u=n.apply(a,r)):l||e.trailing===!1||(l=setTimeout(o,s)),u}}); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.helpers.dimensions', []).factory('dimensions', [ |
| | | '$document', |
| | | '$window', |
| | | function ($document, $window) { |
| | | var jqLite = angular.element; |
| | | var fn = {}; |
| | | /** |
| | | * Test the element nodeName |
| | | * @param element |
| | | * @param name |
| | | */ |
| | | var nodeName = fn.nodeName = function (element, name) { |
| | | return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase(); |
| | | }; |
| | | /** |
| | | * Returns the element computed style |
| | | * @param element |
| | | * @param prop |
| | | * @param extra |
| | | */ |
| | | fn.css = function (element, prop, extra) { |
| | | var value; |
| | | if (element.currentStyle) { |
| | | //IE |
| | | value = element.currentStyle[prop]; |
| | | } else if (window.getComputedStyle) { |
| | | value = window.getComputedStyle(element)[prop]; |
| | | } else { |
| | | value = element.style[prop]; |
| | | } |
| | | return extra === true ? parseFloat(value) || 0 : value; |
| | | }; |
| | | /** |
| | | * Provides read-only equivalent of jQuery's offset function: |
| | | * @required-by bootstrap-tooltip, bootstrap-affix |
| | | * @url http://api.jquery.com/offset/ |
| | | * @param element |
| | | */ |
| | | fn.offset = function (element) { |
| | | var boxRect = element.getBoundingClientRect(); |
| | | var docElement = element.ownerDocument; |
| | | return { |
| | | width: boxRect.width || element.offsetWidth, |
| | | height: boxRect.height || element.offsetHeight, |
| | | top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0), |
| | | left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0) |
| | | }; |
| | | }; |
| | | /** |
| | | * Provides read-only equivalent of jQuery's position function |
| | | * @required-by bootstrap-tooltip, bootstrap-affix |
| | | * @url http://api.jquery.com/offset/ |
| | | * @param element |
| | | */ |
| | | fn.position = function (element) { |
| | | var offsetParentRect = { |
| | | top: 0, |
| | | left: 0 |
| | | }, offsetParentElement, offset; |
| | | // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent |
| | | if (fn.css(element, 'position') === 'fixed') { |
| | | // We assume that getBoundingClientRect is available when computed position is fixed |
| | | offset = element.getBoundingClientRect(); |
| | | } else { |
| | | // Get *real* offsetParentElement |
| | | offsetParentElement = offsetParent(element); |
| | | offset = fn.offset(element); |
| | | // Get correct offsets |
| | | offset = fn.offset(element); |
| | | if (!nodeName(offsetParentElement, 'html')) { |
| | | offsetParentRect = fn.offset(offsetParentElement); |
| | | } |
| | | // Add offsetParent borders |
| | | offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true); |
| | | offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true); |
| | | } |
| | | // Subtract parent offsets and element margins |
| | | return { |
| | | width: element.offsetWidth, |
| | | height: element.offsetHeight, |
| | | top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true), |
| | | left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true) |
| | | }; |
| | | }; |
| | | /** |
| | | * Returns the closest, non-statically positioned offsetParent of a given element |
| | | * @required-by fn.position |
| | | * @param element |
| | | */ |
| | | var offsetParent = function offsetParentElement(element) { |
| | | var docElement = element.ownerDocument; |
| | | var offsetParent = element.offsetParent || docElement; |
| | | if (nodeName(offsetParent, '#document')) |
| | | return docElement.documentElement; |
| | | while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') { |
| | | offsetParent = offsetParent.offsetParent; |
| | | } |
| | | return offsetParent || docElement.documentElement; |
| | | }; |
| | | /** |
| | | * Provides equivalent of jQuery's height function |
| | | * @required-by bootstrap-affix |
| | | * @url http://api.jquery.com/height/ |
| | | * @param element |
| | | * @param outer |
| | | */ |
| | | fn.height = function (element, outer) { |
| | | var value = element.offsetHeight; |
| | | if (outer) { |
| | | value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true); |
| | | } else { |
| | | value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true); |
| | | } |
| | | return value; |
| | | }; |
| | | /** |
| | | * Provides equivalent of jQuery's width function |
| | | * @required-by bootstrap-affix |
| | | * @url http://api.jquery.com/width/ |
| | | * @param element |
| | | * @param outer |
| | | */ |
| | | fn.width = function (element, outer) { |
| | | var value = element.offsetWidth; |
| | | if (outer) { |
| | | value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true); |
| | | } else { |
| | | value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true); |
| | | } |
| | | return value; |
| | | }; |
| | | return fn; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.helpers.dimensions",[]).factory("dimensions",["$document","$window",function(){var t=(angular.element,{}),e=t.nodeName=function(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()};t.css=function(t,e,o){var n;return n=t.currentStyle?t.currentStyle[e]:window.getComputedStyle?window.getComputedStyle(t)[e]:t.style[e],o===!0?parseFloat(n)||0:n},t.offset=function(t){var e=t.getBoundingClientRect(),o=t.ownerDocument;return{width:e.width||t.offsetWidth,height:e.height||t.offsetHeight,top:e.top+(window.pageYOffset||o.documentElement.scrollTop)-(o.documentElement.clientTop||0),left:e.left+(window.pageXOffset||o.documentElement.scrollLeft)-(o.documentElement.clientLeft||0)}},t.position=function(n){var s,i,r={top:0,left:0};return"fixed"===t.css(n,"position")?i=n.getBoundingClientRect():(s=o(n),i=t.offset(n),i=t.offset(n),e(s,"html")||(r=t.offset(s)),r.top+=t.css(s,"borderTopWidth",!0),r.left+=t.css(s,"borderLeftWidth",!0)),{width:n.offsetWidth,height:n.offsetHeight,top:i.top-r.top-t.css(n,"marginTop",!0),left:i.left-r.left-t.css(n,"marginLeft",!0)}};var o=function(o){var n=o.ownerDocument,s=o.offsetParent||n;if(e(s,"#document"))return n.documentElement;for(;s&&!e(s,"html")&&"static"===t.css(s,"position");)s=s.offsetParent;return s||n.documentElement};return t.height=function(e,o){var n=e.offsetHeight;return o?n+=t.css(e,"marginTop",!0)+t.css(e,"marginBottom",!0):n-=t.css(e,"paddingTop",!0)+t.css(e,"paddingBottom",!0)+t.css(e,"borderTopWidth",!0)+t.css(e,"borderBottomWidth",!0),n},t.width=function(e,o){var n=e.offsetWidth;return o?n+=t.css(e,"marginLeft",!0)+t.css(e,"marginRight",!0):n-=t.css(e,"paddingLeft",!0)+t.css(e,"paddingRight",!0)+t.css(e,"borderLeftWidth",!0)+t.css(e,"borderRightWidth",!0),n},t}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip']).provider('$dropdown', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'dropdown', |
| | | placement: 'bottom-left', |
| | | template: 'dropdown/dropdown.tpl.html', |
| | | trigger: 'click', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector; |
| | | function DropdownFactory(element, config) { |
| | | var $dropdown = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | $dropdown = $tooltip(element, options); |
| | | // Protected methods |
| | | $dropdown.$onKeyDown = function (evt) { |
| | | if (!/(38|40)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Retrieve focused index |
| | | var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a')); |
| | | if (!items.length) |
| | | return; |
| | | var index; |
| | | angular.forEach(items, function (el, i) { |
| | | if (matchesSelector && matchesSelector.call(el, ':focus')) |
| | | index = i; |
| | | }); |
| | | // Navigate with keyboard |
| | | if (evt.keyCode === 38 && index > 0) |
| | | index--; |
| | | else if (evt.keyCode === 40 && index < items.length - 1) |
| | | index++; |
| | | else if (angular.isUndefined(index)) |
| | | index = 0; |
| | | items.eq(index)[0].focus(); |
| | | }; |
| | | // Overrides |
| | | var show = $dropdown.show; |
| | | $dropdown.show = function () { |
| | | show(); |
| | | setTimeout(function () { |
| | | options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown); |
| | | bodyEl.on('click', onBodyClick); |
| | | }); |
| | | }; |
| | | var hide = $dropdown.hide; |
| | | $dropdown.hide = function () { |
| | | options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown); |
| | | bodyEl.off('click', onBodyClick); |
| | | hide(); |
| | | }; |
| | | // Private functions |
| | | function onBodyClick(evt) { |
| | | if (evt.target === element[0]) |
| | | return; |
| | | return evt.target !== element[0] && $dropdown.hide(); |
| | | } |
| | | return $dropdown; |
| | | } |
| | | return DropdownFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsDropdown', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$dropdown', |
| | | function ($window, $location, $sce, $dropdown) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) { |
| | | scope.content = newValue; |
| | | }, true); |
| | | // Initialize dropdown |
| | | var dropdown = $dropdown(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | dropdown.destroy(); |
| | | options = null; |
| | | dropdown = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var e=this.defaults={animation:"am-fade",prefixClass:"dropdown",placement:"bottom-left",template:"dropdown/dropdown.tpl.html",trigger:"click",container:!1,keyboard:!0,html:!1,delay:0};this.$get=["$window","$rootScope","$tooltip",function(o,t,n){function r(o,r){function c(e){return e.target!==o[0]?e.target!==o[0]&&i.hide():void 0}{var i={},d=angular.extend({},e,r);i.$scope=d.scope&&d.scope.$new()||t.$new()}i=n(o,d),i.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var o=angular.element(i.$element[0].querySelectorAll("li:not(.divider) a"));if(o.length){var t;angular.forEach(o,function(e,o){l&&l.call(e,":focus")&&(t=o)}),38===e.keyCode&&t>0?t--:40===e.keyCode&&t<o.length-1?t++:angular.isUndefined(t)&&(t=0),o.eq(t)[0].focus()}}};var p=i.show;i.show=function(){p(),setTimeout(function(){d.keyboard&&i.$element.on("keydown",i.$onKeyDown),a.on("click",c)})};var u=i.hide;return i.hide=function(){d.keyboard&&i.$element.off("keydown",i.$onKeyDown),a.off("click",c),u()},i}var a=angular.element(o.document.body),l=Element.prototype.matchesSelector||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector;return r}]}).directive("bsDropdown",["$window","$location","$sce","$dropdown",function(e,o,t,n){return{restrict:"EAC",scope:!0,link:function(e,o,t){var r={scope:e};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template"],function(e){angular.isDefined(t[e])&&(r[e]=t[e])}),t.bsDropdown&&e.$watch(t.bsDropdown,function(o){e.content=o},!0);var a=n(o,r);e.$on("$destroy",function(){a.destroy(),r=null,a=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.dropdown').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.dropdown").run(["$templateCache",function(e){e.put("dropdown/dropdown.tpl.html",'<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions']).provider('$modal', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | backdropAnimation: 'am-fade', |
| | | prefixClass: 'modal', |
| | | prefixEvent: 'modal', |
| | | placement: 'top', |
| | | template: 'modal/modal.tpl.html', |
| | | contentTemplate: false, |
| | | container: false, |
| | | element: null, |
| | | backdrop: true, |
| | | keyboard: true, |
| | | html: false, |
| | | show: true |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$compile', |
| | | '$q', |
| | | '$templateCache', |
| | | '$http', |
| | | '$animate', |
| | | '$timeout', |
| | | '$sce', |
| | | 'dimensions', |
| | | function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) { |
| | | var forEach = angular.forEach; |
| | | var trim = String.prototype.trim; |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | var bodyElement = angular.element($window.document.body); |
| | | var htmlReplaceRegExp = /ng-bind="/gi; |
| | | function ModalFactory(config) { |
| | | var $modal = {}; |
| | | // Common vars |
| | | var options = $modal.$options = angular.extend({}, defaults, config); |
| | | $modal.$promise = fetchTemplate(options.template); |
| | | var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | if (!options.element && !options.container) { |
| | | options.container = 'body'; |
| | | } |
| | | // Support scope as string options |
| | | forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | if (options[key]) |
| | | scope[key] = $sce.trustAsHtml(options[key]); |
| | | }); |
| | | // Provide scope helpers |
| | | scope.$hide = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.hide(); |
| | | }); |
| | | }; |
| | | scope.$show = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.show(); |
| | | }); |
| | | }; |
| | | scope.$toggle = function () { |
| | | scope.$$postDigest(function () { |
| | | $modal.toggle(); |
| | | }); |
| | | }; |
| | | // Support contentTemplate option |
| | | if (options.contentTemplate) { |
| | | $modal.$promise = $modal.$promise.then(function (template) { |
| | | var templateEl = angular.element(template); |
| | | return fetchTemplate(options.contentTemplate).then(function (contentTemplate) { |
| | | var contentEl = findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate); |
| | | // Drop the default footer as you probably don't want it if you use a custom contentTemplate |
| | | if (!config.template) |
| | | contentEl.next().remove(); |
| | | return templateEl[0].outerHTML; |
| | | }); |
| | | }); |
| | | } |
| | | // Fetch, compile then initialize modal |
| | | var modalLinker, modalElement; |
| | | var backdropElement = angular.element('<div class="' + options.prefixClass + '-backdrop"/>'); |
| | | $modal.$promise.then(function (template) { |
| | | if (angular.isObject(template)) |
| | | template = template.data; |
| | | if (options.html) |
| | | template = template.replace(htmlReplaceRegExp, 'ng-bind-html="'); |
| | | template = trim.apply(template); |
| | | modalLinker = $compile(template); |
| | | $modal.init(); |
| | | }); |
| | | $modal.init = function () { |
| | | // Options: show |
| | | if (options.show) { |
| | | scope.$$postDigest(function () { |
| | | $modal.show(); |
| | | }); |
| | | } |
| | | }; |
| | | $modal.destroy = function () { |
| | | // Remove element |
| | | if (modalElement) { |
| | | modalElement.remove(); |
| | | modalElement = null; |
| | | } |
| | | if (backdropElement) { |
| | | backdropElement.remove(); |
| | | backdropElement = null; |
| | | } |
| | | // Destroy scope |
| | | scope.$destroy(); |
| | | }; |
| | | $modal.show = function () { |
| | | scope.$emit(options.prefixEvent + '.show.before', $modal); |
| | | var parent = options.container ? findElement(options.container) : null; |
| | | var after = options.container ? null : options.element; |
| | | // Fetch a cloned element linked from template |
| | | modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) { |
| | | }); |
| | | // Set the initial positioning. |
| | | modalElement.css({ display: 'block' }).addClass(options.placement); |
| | | // Options: animation |
| | | if (options.animation) { |
| | | if (options.backdrop) { |
| | | backdropElement.addClass(options.backdropAnimation); |
| | | } |
| | | modalElement.addClass(options.animation); |
| | | } |
| | | if (options.backdrop) { |
| | | $animate.enter(backdropElement, bodyElement, null, function () { |
| | | }); |
| | | } |
| | | $animate.enter(modalElement, parent, after, function () { |
| | | scope.$emit(options.prefixEvent + '.show', $modal); |
| | | }); |
| | | scope.$isShown = true; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Focus once the enter-animation has started |
| | | // Weird PhantomJS bug hack |
| | | var el = modalElement[0]; |
| | | requestAnimationFrame(function () { |
| | | el.focus(); |
| | | }); |
| | | bodyElement.addClass(options.prefixClass + '-open'); |
| | | if (options.animation) { |
| | | bodyElement.addClass(options.prefixClass + '-with-' + options.animation); |
| | | } |
| | | // Bind events |
| | | if (options.backdrop) { |
| | | modalElement.on('click', hideOnBackdropClick); |
| | | backdropElement.on('click', hideOnBackdropClick); |
| | | } |
| | | if (options.keyboard) { |
| | | modalElement.on('keyup', $modal.$onKeyUp); |
| | | } |
| | | }; |
| | | $modal.hide = function () { |
| | | scope.$emit(options.prefixEvent + '.hide.before', $modal); |
| | | $animate.leave(modalElement, function () { |
| | | scope.$emit(options.prefixEvent + '.hide', $modal); |
| | | bodyElement.removeClass(options.prefixClass + '-open'); |
| | | if (options.animation) { |
| | | bodyElement.addClass(options.prefixClass + '-with-' + options.animation); |
| | | } |
| | | }); |
| | | if (options.backdrop) { |
| | | $animate.leave(backdropElement, function () { |
| | | }); |
| | | } |
| | | scope.$isShown = false; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Unbind events |
| | | if (options.backdrop) { |
| | | modalElement.off('click', hideOnBackdropClick); |
| | | backdropElement.off('click', hideOnBackdropClick); |
| | | } |
| | | if (options.keyboard) { |
| | | modalElement.off('keyup', $modal.$onKeyUp); |
| | | } |
| | | }; |
| | | $modal.toggle = function () { |
| | | scope.$isShown ? $modal.hide() : $modal.show(); |
| | | }; |
| | | $modal.focus = function () { |
| | | modalElement[0].focus(); |
| | | }; |
| | | // Protected methods |
| | | $modal.$onKeyUp = function (evt) { |
| | | evt.which === 27 && $modal.hide(); |
| | | }; |
| | | // Private methods |
| | | function hideOnBackdropClick(evt) { |
| | | if (evt.target !== evt.currentTarget) |
| | | return; |
| | | options.backdrop === 'static' ? $modal.focus() : $modal.hide(); |
| | | } |
| | | return $modal; |
| | | } |
| | | // Helper functions |
| | | function findElement(query, element) { |
| | | return angular.element((element || document).querySelectorAll(query)); |
| | | } |
| | | function fetchTemplate(template) { |
| | | return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) { |
| | | if (angular.isObject(res)) { |
| | | $templateCache.put(template, res.data); |
| | | return res.data; |
| | | } |
| | | return res; |
| | | }); |
| | | } |
| | | return ModalFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsModal', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$modal', |
| | | function ($window, $location, $sce, $modal) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | element: element, |
| | | show: false |
| | | }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'backdrop', |
| | | 'keyboard', |
| | | 'html', |
| | | 'container', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | }, true); |
| | | // Initialize modal |
| | | var modal = $modal(options); |
| | | // Trigger |
| | | element.on(attr.trigger || 'click', modal.toggle); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | modal.destroy(); |
| | | options = null; |
| | | modal = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.helpers.dimensions"]).provider("$modal",function(){var n=this.defaults={animation:"am-fade",backdropAnimation:"am-fade",prefixClass:"modal",prefixEvent:"modal",placement:"top",template:"modal/modal.tpl.html",contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","$sce","dimensions",function(e,t,o,a,i,r,c,l,s){function u(e){function a(n){n.target===n.currentTarget&&("static"===r.backdrop?i.focus():i.hide())}var i={},r=i.$options=angular.extend({},n,e);i.$promise=m(r.template);var l=i.$scope=r.scope&&r.scope.$new()||t.$new();r.element||r.container||(r.container="body"),p(["title","content"],function(n){r[n]&&(l[n]=s.trustAsHtml(r[n]))}),l.$hide=function(){l.$$postDigest(function(){i.hide()})},l.$show=function(){l.$$postDigest(function(){i.show()})},l.$toggle=function(){l.$$postDigest(function(){i.toggle()})},r.contentTemplate&&(i.$promise=i.$promise.then(function(n){var t=angular.element(n);return m(r.contentTemplate).then(function(n){var o=d('[ng-bind="content"]',t[0]).removeAttr("ng-bind").html(n);return e.template||o.next().remove(),t[0].outerHTML})}));var u,b,v=angular.element('<div class="'+r.prefixClass+'-backdrop"/>');return i.$promise.then(function(n){angular.isObject(n)&&(n=n.data),r.html&&(n=n.replace(g,'ng-bind-html="')),n=f.apply(n),u=o(n),i.init()}),i.init=function(){r.show&&l.$$postDigest(function(){i.show()})},i.destroy=function(){b&&(b.remove(),b=null),v&&(v.remove(),v=null),l.$destroy()},i.show=function(){l.$emit(r.prefixEvent+".show.before",i);var n=r.container?d(r.container):null,e=r.container?null:r.element;b=i.$element=u(l,function(){}),b.css({display:"block"}).addClass(r.placement),r.animation&&(r.backdrop&&v.addClass(r.backdropAnimation),b.addClass(r.animation)),r.backdrop&&c.enter(v,h,null,function(){}),c.enter(b,n,e,function(){l.$emit(r.prefixEvent+".show",i)}),l.$isShown=!0,l.$$phase||l.$root&&l.$root.$$phase||l.$digest();var t=b[0];$(function(){t.focus()}),h.addClass(r.prefixClass+"-open"),r.animation&&h.addClass(r.prefixClass+"-with-"+r.animation),r.backdrop&&(b.on("click",a),v.on("click",a)),r.keyboard&&b.on("keyup",i.$onKeyUp)},i.hide=function(){l.$emit(r.prefixEvent+".hide.before",i),c.leave(b,function(){l.$emit(r.prefixEvent+".hide",i),h.removeClass(r.prefixClass+"-open"),r.animation&&h.addClass(r.prefixClass+"-with-"+r.animation)}),r.backdrop&&c.leave(v,function(){}),l.$isShown=!1,l.$$phase||l.$root&&l.$root.$$phase||l.$digest(),r.backdrop&&(b.off("click",a),v.off("click",a)),r.keyboard&&b.off("keyup",i.$onKeyUp)},i.toggle=function(){l.$isShown?i.hide():i.show()},i.focus=function(){b[0].focus()},i.$onKeyUp=function(n){27===n.which&&i.hide()},i}function d(n,e){return angular.element((e||document).querySelectorAll(n))}function m(n){return a.when(i.get(n)||r.get(n)).then(function(e){return angular.isObject(e)?(i.put(n,e.data),e.data):e})}var p=angular.forEach,f=String.prototype.trim,$=e.requestAnimationFrame||e.setTimeout,h=angular.element(e.document.body),g=/ng-bind="/gi;return u}]}).directive("bsModal",["$window","$location","$sce","$modal",function(n,e,t,o){return{restrict:"EAC",scope:!0,link:function(n,e,a){var i={scope:n,element:e,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(n){angular.isDefined(a[n])&&(i[n]=a[n])}),angular.forEach(["title","content"],function(e){a[e]&&a.$observe(e,function(o){n[e]=t.trustAsHtml(o)})}),a.bsModal&&n.$watch(a.bsModal,function(e){angular.isObject(e)?angular.extend(n,e):n.content=e},!0);var r=o(i);e.on(a.trigger||"click",r.toggle),n.$on("$destroy",function(){r.destroy(),i=null,r=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.modal').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('modal/modal.tpl.html', '<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.modal").run(["$templateCache",function(t){t.put("modal/modal.tpl.html",'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">×</button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.navbar', []).provider('$navbar', function () { |
| | | var defaults = this.defaults = { |
| | | activeClass: 'active', |
| | | routeAttr: 'data-match-route', |
| | | strict: false |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsNavbar', [ |
| | | '$window', |
| | | '$location', |
| | | '$navbar', |
| | | function ($window, $location, $navbar) { |
| | | var defaults = $navbar.defaults; |
| | | return { |
| | | restrict: 'A', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = angular.copy(defaults); |
| | | angular.forEach(Object.keys(defaults), function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Watch for the $location |
| | | scope.$watch(function () { |
| | | return $location.path(); |
| | | }, function (newValue, oldValue) { |
| | | var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']'); |
| | | angular.forEach(liElements, function (li) { |
| | | var liElement = angular.element(li); |
| | | var pattern = liElement.attr(options.routeAttr).replace('/', '\\/'); |
| | | if (options.strict) { |
| | | pattern = '^' + pattern + '$'; |
| | | } |
| | | var regexp = new RegExp(pattern, ['i']); |
| | | if (regexp.test(newValue)) { |
| | | liElement.addClass(options.activeClass); |
| | | } else { |
| | | liElement.removeClass(options.activeClass); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.navbar",[]).provider("$navbar",function(){var t=this.defaults={activeClass:"active",routeAttr:"data-match-route",strict:!1};this.$get=function(){return{defaults:t}}}).directive("bsNavbar",["$window","$location","$navbar",function(t,a,r){var e=r.defaults;return{restrict:"A",link:function(t,r,n){var i=angular.copy(e);angular.forEach(Object.keys(e),function(t){angular.isDefined(n[t])&&(i[t]=n[t])}),t.$watch(function(){return a.path()},function(t){var a=r[0].querySelectorAll("li["+i.routeAttr+"]");angular.forEach(a,function(a){var r=angular.element(a),e=r.attr(i.routeAttr).replace("/","\\/");i.strict&&(e="^"+e+"$");var n=new RegExp(e,["i"]);n.test(t)?r.addClass(i.activeClass):r.removeClass(i.activeClass)})})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.helpers.parseOptions', []).provider('$parseOptions', function () { |
| | | var defaults = this.defaults = { regexp: /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/ }; |
| | | this.$get = [ |
| | | '$parse', |
| | | '$q', |
| | | function ($parse, $q) { |
| | | function ParseOptionsFactory(attr, config) { |
| | | var $parseOptions = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $parseOptions.$values = []; |
| | | // Private vars |
| | | var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn; |
| | | $parseOptions.init = function () { |
| | | $parseOptions.$match = match = attr.match(options.regexp); |
| | | displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], groupByFn = $parse(match[3] || ''), valueFn = $parse(match[2] ? match[1] : valueName), valuesFn = $parse(match[7]); |
| | | }; |
| | | $parseOptions.valuesFn = function (scope, controller) { |
| | | return $q.when(valuesFn(scope, controller)).then(function (values) { |
| | | $parseOptions.$values = values ? parseValues(values, scope) : {}; |
| | | return $parseOptions.$values; |
| | | }); |
| | | }; |
| | | // Private functions |
| | | function parseValues(values, scope) { |
| | | return values.map(function (match, index) { |
| | | var locals = {}, label, value; |
| | | locals[valueName] = match; |
| | | label = displayFn(scope, locals); |
| | | value = valueFn(scope, locals) || index; |
| | | return { |
| | | label: label, |
| | | value: value |
| | | }; |
| | | }); |
| | | } |
| | | $parseOptions.init(); |
| | | return $parseOptions; |
| | | } |
| | | return ParseOptionsFactory; |
| | | } |
| | | ]; |
| | | }); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.helpers.parseOptions",[]).provider("$parseOptions",function(){var n=this.defaults={regexp:/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/};this.$get=["$parse","$q",function(s,r){function e(e,t){function a(n,s){return n.map(function(n,r){var e,t,a={};return a[c]=n,e=o(s,a),t=f(s,a)||r,{label:e,value:t}})}var u={},i=angular.extend({},n,t);u.$values=[];var $,o,c,l,p,f,v;return u.init=function(){u.$match=$=e.match(i.regexp),o=s($[2]||$[1]),c=$[4]||$[6],l=$[5],p=s($[3]||""),f=s($[2]?$[1]:c),v=s($[7])},u.valuesFn=function(n,s){return r.when(v(n,s)).then(function(s){return u.$values=s?a(s,n):{},u.$values})},u.init(),u}return e}]}); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).provider('$popover', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | container: false, |
| | | target: false, |
| | | placement: 'right', |
| | | template: 'popover/popover.tpl.html', |
| | | contentTemplate: false, |
| | | trigger: 'click', |
| | | keyboard: true, |
| | | html: false, |
| | | title: '', |
| | | content: '', |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$tooltip', |
| | | function ($tooltip) { |
| | | function PopoverFactory(element, config) { |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | var $popover = $tooltip(element, options); |
| | | // Support scope as string options [/*title, */content] |
| | | if (options.content) { |
| | | $popover.$scope.content = options.content; |
| | | } |
| | | return $popover; |
| | | } |
| | | return PopoverFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsPopover', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$popover', |
| | | function ($window, $location, $sce, $popover) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'container', |
| | | 'target', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Support scope as data-attrs |
| | | angular.forEach([ |
| | | 'title', |
| | | 'content' |
| | | ], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | angular.isDefined(oldValue) && requestAnimationFrame(function () { |
| | | popover && popover.$applyPlacement(); |
| | | }); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.content = newValue; |
| | | } |
| | | angular.isDefined(oldValue) && requestAnimationFrame(function () { |
| | | popover && popover.$applyPlacement(); |
| | | }); |
| | | }, true); |
| | | // Initialize popover |
| | | var popover = $popover(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | popover.destroy(); |
| | | options = null; |
| | | popover = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.popover",["mgcrea.ngStrap.tooltip"]).provider("$popover",function(){var t=this.defaults={animation:"am-fade",container:!1,target:!1,placement:"right",template:"popover/popover.tpl.html",contentTemplate:!1,trigger:"click",keyboard:!0,html:!1,title:"",content:"",delay:0};this.$get=["$tooltip",function(e){function n(n,o){var a=angular.extend({},t,o),r=e(n,a);return a.content&&(r.$scope.content=a.content),r}return n}]}).directive("bsPopover",["$window","$location","$sce","$popover",function(t,e,n,o){var a=t.requestAnimationFrame||t.setTimeout;return{restrict:"EAC",scope:!0,link:function(t,e,r){var i={scope:t};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation"],function(t){angular.isDefined(r[t])&&(i[t]=r[t])}),angular.forEach(["title","content"],function(e){r[e]&&r.$observe(e,function(o,r){t[e]=n.trustAsHtml(o),angular.isDefined(r)&&a(function(){c&&c.$applyPlacement()})})}),r.bsPopover&&t.$watch(r.bsPopover,function(e,n){angular.isObject(e)?angular.extend(t,e):t.content=e,angular.isDefined(n)&&a(function(){c&&c.$applyPlacement()})},!0);var c=o(e,i);t.$on("$destroy",function(){c.destroy(),i=null,c=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.popover').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('popover/popover.tpl.html', '<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.popover").run(["$templateCache",function(t){t.put("popover/popover.tpl.html",'<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.version.minor < 3 && angular.version.dot < 14 && angular.module('ng').factory('$$rAF', [ |
| | | '$window', |
| | | '$timeout', |
| | | function ($window, $timeout) { |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame; |
| | | var cancelAnimationFrame = $window.cancelAnimationFrame || $window.webkitCancelAnimationFrame || $window.mozCancelAnimationFrame || $window.webkitCancelRequestAnimationFrame; |
| | | var rafSupported = !!requestAnimationFrame; |
| | | var raf = rafSupported ? function (fn) { |
| | | var id = requestAnimationFrame(fn); |
| | | return function () { |
| | | cancelAnimationFrame(id); |
| | | }; |
| | | } : function (fn) { |
| | | var timer = $timeout(fn, 16.66, false); |
| | | // 1000 / 60 = 16.666 |
| | | return function () { |
| | | $timeout.cancel(timer); |
| | | }; |
| | | }; |
| | | raf.supported = rafSupported; |
| | | return raf; |
| | | } |
| | | ]); // .factory('$$animateReflow', function($$rAF, $document) { |
| | | // var bodyEl = $document[0].body; |
| | | // return function(fn) { |
| | | // //the returned function acts as the cancellation function |
| | | // return $$rAF(function() { |
| | | // //the line below will force the browser to perform a repaint |
| | | // //so that all the animated elements within the animation frame |
| | | // //will be properly updated and drawn on screen. This is |
| | | // //required to perform multi-class CSS based animations with |
| | | // //Firefox. DO NOT REMOVE THIS LINE. |
| | | // var a = bodyEl.offsetWidth + 1; |
| | | // fn(); |
| | | // }); |
| | | // }; |
| | | // }); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.version.minor<3&&angular.version.dot<14&&angular.module("ng").factory("$$rAF",["$window","$timeout",function(n,e){var a=n.requestAnimationFrame||n.webkitRequestAnimationFrame||n.mozRequestAnimationFrame,t=n.cancelAnimationFrame||n.webkitCancelAnimationFrame||n.mozCancelAnimationFrame||n.webkitCancelRequestAnimationFrame,i=!!a,r=i?function(n){var e=a(n);return function(){t(e)}}:function(n){var a=e(n,16.66,!1);return function(){e.cancel(a)}};return r.supported=i,r}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.scrollspy', [ |
| | | 'mgcrea.ngStrap.helpers.debounce', |
| | | 'mgcrea.ngStrap.helpers.dimensions' |
| | | ]).provider('$scrollspy', function () { |
| | | // Pool of registered spies |
| | | var spies = this.$$spies = {}; |
| | | var defaults = this.defaults = { |
| | | debounce: 150, |
| | | throttle: 100, |
| | | offset: 100 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | 'dimensions', |
| | | 'debounce', |
| | | 'throttle', |
| | | function ($window, $document, $rootScope, dimensions, debounce, throttle) { |
| | | var windowEl = angular.element($window); |
| | | var docEl = angular.element($document.prop('documentElement')); |
| | | var bodyEl = angular.element($window.document.body); |
| | | // Helper functions |
| | | function nodeName(element, name) { |
| | | return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase(); |
| | | } |
| | | function ScrollSpyFactory(config) { |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | if (!options.element) |
| | | options.element = bodyEl; |
| | | var isWindowSpy = nodeName(options.element, 'body'); |
| | | var scrollEl = isWindowSpy ? windowEl : options.element; |
| | | var scrollId = isWindowSpy ? 'window' : options.id; |
| | | // Use existing spy |
| | | if (spies[scrollId]) { |
| | | spies[scrollId].$$count++; |
| | | return spies[scrollId]; |
| | | } |
| | | var $scrollspy = {}; |
| | | // Private vars |
| | | var unbindViewContentLoaded, unbindIncludeContentLoaded; |
| | | var trackedElements = $scrollspy.$trackedElements = []; |
| | | var sortedElements = []; |
| | | var activeTarget; |
| | | var debouncedCheckPosition; |
| | | var throttledCheckPosition; |
| | | var debouncedCheckOffsets; |
| | | var viewportHeight; |
| | | var scrollTop; |
| | | $scrollspy.init = function () { |
| | | // Setup internal ref counter |
| | | this.$$count = 1; |
| | | // Bind events |
| | | debouncedCheckPosition = debounce(this.checkPosition, options.debounce); |
| | | throttledCheckPosition = throttle(this.checkPosition, options.throttle); |
| | | scrollEl.on('click', this.checkPositionWithEventLoop); |
| | | windowEl.on('resize', debouncedCheckPosition); |
| | | scrollEl.on('scroll', throttledCheckPosition); |
| | | debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce); |
| | | unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets); |
| | | unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets); |
| | | debouncedCheckOffsets(); |
| | | // Register spy for reuse |
| | | if (scrollId) { |
| | | spies[scrollId] = $scrollspy; |
| | | } |
| | | }; |
| | | $scrollspy.destroy = function () { |
| | | // Check internal ref counter |
| | | this.$$count--; |
| | | if (this.$$count > 0) { |
| | | return; |
| | | } |
| | | // Unbind events |
| | | scrollEl.off('click', this.checkPositionWithEventLoop); |
| | | windowEl.off('resize', debouncedCheckPosition); |
| | | scrollEl.off('scroll', debouncedCheckPosition); |
| | | unbindViewContentLoaded(); |
| | | unbindIncludeContentLoaded(); |
| | | if (scrollId) { |
| | | delete spies[scrollId]; |
| | | } |
| | | }; |
| | | $scrollspy.checkPosition = function () { |
| | | // Not ready yet |
| | | if (!sortedElements.length) |
| | | return; |
| | | // Calculate the scroll position |
| | | scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0; |
| | | // Calculate the viewport height for use by the components |
| | | viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight')); |
| | | // Activate first element if scroll is smaller |
| | | if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) { |
| | | return $scrollspy.$activateElement(sortedElements[0]); |
| | | } |
| | | // Activate proper element |
| | | for (var i = sortedElements.length; i--;) { |
| | | if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) |
| | | continue; |
| | | if (activeTarget === sortedElements[i].target) |
| | | continue; |
| | | if (scrollTop < sortedElements[i].offsetTop) |
| | | continue; |
| | | if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) |
| | | continue; |
| | | return $scrollspy.$activateElement(sortedElements[i]); |
| | | } |
| | | }; |
| | | $scrollspy.checkPositionWithEventLoop = function () { |
| | | setTimeout(this.checkPosition, 1); |
| | | }; |
| | | // Protected methods |
| | | $scrollspy.$activateElement = function (element) { |
| | | if (activeTarget) { |
| | | var activeElement = $scrollspy.$getTrackedElement(activeTarget); |
| | | if (activeElement) { |
| | | activeElement.source.removeClass('active'); |
| | | if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) { |
| | | activeElement.source.parent().parent().removeClass('active'); |
| | | } |
| | | } |
| | | } |
| | | activeTarget = element.target; |
| | | element.source.addClass('active'); |
| | | if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) { |
| | | element.source.parent().parent().addClass('active'); |
| | | } |
| | | }; |
| | | $scrollspy.$getTrackedElement = function (target) { |
| | | return trackedElements.filter(function (obj) { |
| | | return obj.target === target; |
| | | })[0]; |
| | | }; |
| | | // Track offsets behavior |
| | | $scrollspy.checkOffsets = function () { |
| | | angular.forEach(trackedElements, function (trackedElement) { |
| | | var targetElement = document.querySelector(trackedElement.target); |
| | | trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null; |
| | | if (options.offset && trackedElement.offsetTop !== null) |
| | | trackedElement.offsetTop -= options.offset * 1; |
| | | }); |
| | | sortedElements = trackedElements.filter(function (el) { |
| | | return el.offsetTop !== null; |
| | | }).sort(function (a, b) { |
| | | return a.offsetTop - b.offsetTop; |
| | | }); |
| | | debouncedCheckPosition(); |
| | | }; |
| | | $scrollspy.trackElement = function (target, source) { |
| | | trackedElements.push({ |
| | | target: target, |
| | | source: source |
| | | }); |
| | | }; |
| | | $scrollspy.untrackElement = function (target, source) { |
| | | var toDelete; |
| | | for (var i = trackedElements.length; i--;) { |
| | | if (trackedElements[i].target === target && trackedElements[i].source === source) { |
| | | toDelete = i; |
| | | break; |
| | | } |
| | | } |
| | | trackedElements = trackedElements.splice(toDelete, 1); |
| | | }; |
| | | $scrollspy.activate = function (i) { |
| | | trackedElements[i].addClass('active'); |
| | | }; |
| | | // Initialize plugin |
| | | $scrollspy.init(); |
| | | return $scrollspy; |
| | | } |
| | | return ScrollSpyFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsScrollspy', [ |
| | | '$rootScope', |
| | | 'debounce', |
| | | 'dimensions', |
| | | '$scrollspy', |
| | | function ($rootScope, debounce, dimensions, $scrollspy) { |
| | | return { |
| | | restrict: 'EAC', |
| | | link: function postLink(scope, element, attr) { |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'offset', |
| | | 'target' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | var scrollspy = $scrollspy(options); |
| | | scrollspy.trackElement(options.target, element); |
| | | scope.$on('$destroy', function () { |
| | | scrollspy.untrackElement(options.target, element); |
| | | scrollspy.destroy(); |
| | | options = null; |
| | | scrollspy = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]).directive('bsScrollspyList', [ |
| | | '$rootScope', |
| | | 'debounce', |
| | | 'dimensions', |
| | | '$scrollspy', |
| | | function ($rootScope, debounce, dimensions, $scrollspy) { |
| | | return { |
| | | restrict: 'A', |
| | | compile: function postLink(element, attr) { |
| | | var children = element[0].querySelectorAll('li > a[href]'); |
| | | angular.forEach(children, function (child) { |
| | | var childEl = angular.element(child); |
| | | childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href')); |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.helpers.debounce","mgcrea.ngStrap.helpers.dimensions"]).provider("$scrollspy",function(){var e=this.$$spies={},t=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(n,o,r,c,i,s){function a(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function l(o){var l=angular.extend({},t,o);l.element||(l.element=p);var d=a(l.element,"body"),h=d?u:l.element,m=d?"window":l.id;if(e[m])return e[m].$$count++,e[m];var g,v,$,k,E,T,y,b,C={},S=C.$trackedElements=[],L=[];return C.init=function(){this.$$count=1,k=i(this.checkPosition,l.debounce),E=s(this.checkPosition,l.throttle),h.on("click",this.checkPositionWithEventLoop),u.on("resize",k),h.on("scroll",E),T=i(this.checkOffsets,l.debounce),g=r.$on("$viewContentLoaded",T),v=r.$on("$includeContentLoaded",T),T(),m&&(e[m]=C)},C.destroy=function(){this.$$count--,this.$$count>0||(h.off("click",this.checkPositionWithEventLoop),u.off("resize",k),h.off("scroll",k),g(),v(),m&&delete e[m])},C.checkPosition=function(){if(L.length){if(b=(d?n.pageYOffset:h.prop("scrollTop"))||0,y=Math.max(n.innerHeight,f.prop("clientHeight")),b<L[0].offsetTop&&$!==L[0].target)return C.$activateElement(L[0]);for(var e=L.length;e--;)if(!angular.isUndefined(L[e].offsetTop)&&null!==L[e].offsetTop&&$!==L[e].target&&!(b<L[e].offsetTop||L[e+1]&&b>L[e+1].offsetTop))return C.$activateElement(L[e])}},C.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},C.$activateElement=function(e){if($){var t=C.$getTrackedElement($);t&&(t.source.removeClass("active"),a(t.source,"li")&&a(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}$=e.target,e.source.addClass("active"),a(e.source,"li")&&a(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},C.$getTrackedElement=function(e){return S.filter(function(t){return t.target===e})[0]},C.checkOffsets=function(){angular.forEach(S,function(e){var t=document.querySelector(e.target);e.offsetTop=t?c.offset(t).top:null,l.offset&&null!==e.offsetTop&&(e.offsetTop-=1*l.offset)}),L=S.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),k()},C.trackElement=function(e,t){S.push({target:e,source:t})},C.untrackElement=function(e,t){for(var n,o=S.length;o--;)if(S[o].target===e&&S[o].source===t){n=o;break}S=S.splice(n,1)},C.activate=function(e){S[e].addClass("active")},C.init(),C}var u=angular.element(n),f=angular.element(o.prop("documentElement")),p=angular.element(n.document.body);return l}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(e,t,n,o){return{restrict:"EAC",link:function(e,t,n){var r={scope:e};angular.forEach(["offset","target"],function(e){angular.isDefined(n[e])&&(r[e]=n[e])});var c=o(r);c.trackElement(r.target,t),e.$on("$destroy",function(){c.untrackElement(r.target,t),c.destroy(),r=null,c=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,function(e){var t=angular.element(e);t.parent().attr("bs-scrollspy","").attr("data-target",t.attr("href"))})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.select', [ |
| | | 'mgcrea.ngStrap.tooltip', |
| | | 'mgcrea.ngStrap.helpers.parseOptions' |
| | | ]).provider('$select', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'select', |
| | | placement: 'bottom-left', |
| | | template: 'select/select.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | multiple: false, |
| | | sort: true, |
| | | caretHtml: ' <span class="caret"></span>', |
| | | placeholder: 'Choose among the following...', |
| | | maxLength: 3, |
| | | maxLengthHtml: 'selected', |
| | | iconCheckmark: 'glyphicon glyphicon-ok' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | function SelectFactory(element, controller, config) { |
| | | var $select = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $select = $tooltip(element, options); |
| | | var scope = $select.$scope; |
| | | scope.$matches = []; |
| | | scope.$activeIndex = 0; |
| | | scope.$isMultiple = options.multiple; |
| | | scope.$iconCheckmark = options.iconCheckmark; |
| | | scope.$activate = function (index) { |
| | | scope.$$postDigest(function () { |
| | | $select.activate(index); |
| | | }); |
| | | }; |
| | | scope.$select = function (index, evt) { |
| | | scope.$$postDigest(function () { |
| | | $select.select(index); |
| | | }); |
| | | }; |
| | | scope.$isVisible = function () { |
| | | return $select.$isVisible(); |
| | | }; |
| | | scope.$isActive = function (index) { |
| | | return $select.$isActive(index); |
| | | }; |
| | | // Public methods |
| | | $select.update = function (matches) { |
| | | scope.$matches = matches; |
| | | $select.$updateActiveIndex(); |
| | | }; |
| | | $select.activate = function (index) { |
| | | if (options.multiple) { |
| | | scope.$activeIndex.sort(); |
| | | $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index); |
| | | if (options.sort) |
| | | scope.$activeIndex.sort(); |
| | | } else { |
| | | scope.$activeIndex = index; |
| | | } |
| | | return scope.$activeIndex; |
| | | }; |
| | | $select.select = function (index) { |
| | | var value = scope.$matches[index].value; |
| | | scope.$apply(function () { |
| | | $select.activate(index); |
| | | if (options.multiple) { |
| | | controller.$setViewValue(scope.$activeIndex.map(function (index) { |
| | | return scope.$matches[index].value; |
| | | })); |
| | | } else { |
| | | controller.$setViewValue(value); |
| | | // Hide if single select |
| | | $select.hide(); |
| | | } |
| | | }); |
| | | // Emit event |
| | | scope.$emit('$select.select', value, index); |
| | | }; |
| | | // Protected methods |
| | | $select.$updateActiveIndex = function () { |
| | | if (controller.$modelValue && scope.$matches.length) { |
| | | if (options.multiple && angular.isArray(controller.$modelValue)) { |
| | | scope.$activeIndex = controller.$modelValue.map(function (value) { |
| | | return $select.$getIndex(value); |
| | | }); |
| | | } else { |
| | | scope.$activeIndex = $select.$getIndex(controller.$modelValue); |
| | | } |
| | | } else if (scope.$activeIndex >= scope.$matches.length) { |
| | | scope.$activeIndex = options.multiple ? [] : 0; |
| | | } |
| | | }; |
| | | $select.$isVisible = function () { |
| | | if (!options.minLength || !controller) { |
| | | return scope.$matches.length; |
| | | } |
| | | // minLength support |
| | | return scope.$matches.length && controller.$viewValue.length >= options.minLength; |
| | | }; |
| | | $select.$isActive = function (index) { |
| | | if (options.multiple) { |
| | | return scope.$activeIndex.indexOf(index) !== -1; |
| | | } else { |
| | | return scope.$activeIndex === index; |
| | | } |
| | | }; |
| | | $select.$getIndex = function (value) { |
| | | var l = scope.$matches.length, i = l; |
| | | if (!l) |
| | | return; |
| | | for (i = l; i--;) { |
| | | if (scope.$matches[i].value === value) |
| | | break; |
| | | } |
| | | if (i < 0) |
| | | return; |
| | | return i; |
| | | }; |
| | | $select.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $select.$onKeyDown = function (evt) { |
| | | if (!/(9|13|38|40)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Select with enter |
| | | if (!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) { |
| | | return $select.select(scope.$activeIndex); |
| | | } |
| | | // Navigate with keyboard |
| | | if (evt.keyCode === 38 && scope.$activeIndex > 0) |
| | | scope.$activeIndex--; |
| | | else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) |
| | | scope.$activeIndex++; |
| | | else if (angular.isUndefined(scope.$activeIndex)) |
| | | scope.$activeIndex = 0; |
| | | scope.$digest(); |
| | | }; |
| | | // Overrides |
| | | var _show = $select.show; |
| | | $select.show = function () { |
| | | _show(); |
| | | if (options.multiple) { |
| | | $select.$element.addClass('select-multiple'); |
| | | } |
| | | setTimeout(function () { |
| | | $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $select.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $select.hide; |
| | | $select.hide = function () { |
| | | $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $select.$onKeyDown); |
| | | } |
| | | _hide(true); |
| | | }; |
| | | return $select; |
| | | } |
| | | SelectFactory.defaults = defaults; |
| | | return SelectFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsSelect', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$select', |
| | | '$parseOptions', |
| | | function ($window, $parse, $q, $select, $parseOptions) { |
| | | var defaults = $select.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'placeholder', |
| | | 'multiple', |
| | | 'maxLength', |
| | | 'maxLengthHtml' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Add support for select markup |
| | | if (element[0].nodeName.toLowerCase() === 'select') { |
| | | var inputEl = element; |
| | | inputEl.css('display', 'none'); |
| | | element = angular.element('<button type="button" class="btn btn-default"></button>'); |
| | | inputEl.after(element); |
| | | } |
| | | // Build proper ngOptions |
| | | var parsedOptions = $parseOptions(attr.ngOptions); |
| | | // Initialize select |
| | | var select = $select(element, controller, options); |
| | | // Watch ngOptions values before filtering for changes |
| | | var watchedOptions = parsedOptions.$match[7].replace(/\|.+/, '').trim(); |
| | | scope.$watch(watchedOptions, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue); |
| | | parsedOptions.valuesFn(scope, controller).then(function (values) { |
| | | select.update(values); |
| | | controller.$render(); |
| | | }); |
| | | }, true); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue); |
| | | select.$updateActiveIndex(); |
| | | controller.$render(); |
| | | }, true); |
| | | // Model rendering in view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | var selected, index; |
| | | if (options.multiple && angular.isArray(controller.$modelValue)) { |
| | | selected = controller.$modelValue.map(function (value) { |
| | | index = select.$getIndex(value); |
| | | return angular.isDefined(index) ? select.$scope.$matches[index].label : false; |
| | | }).filter(angular.isDefined); |
| | | if (selected.length > (options.maxLength || defaults.maxLength)) { |
| | | selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml); |
| | | } else { |
| | | selected = selected.join(', '); |
| | | } |
| | | } else { |
| | | index = select.$getIndex(controller.$modelValue); |
| | | selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false; |
| | | } |
| | | element.html((selected ? selected : attr.placeholder || defaults.placeholder) + defaults.caretHtml); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | select.destroy(); |
| | | options = null; |
| | | select = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.select",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$select",function(){var e=this.defaults={animation:"am-fade",prefixClass:"select",placement:"bottom-left",template:"select/select.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,sort:!0,caretHtml:' <span class="caret"></span>',placeholder:"Choose among the following...",maxLength:3,maxLengthHtml:"selected",iconCheckmark:"glyphicon glyphicon-ok"};this.$get=["$window","$document","$rootScope","$tooltip",function(t,n,a,i){function l(t,n,a){var l={},c=angular.extend({},e,a);l=i(t,c);var r=l.$scope;r.$matches=[],r.$activeIndex=0,r.$isMultiple=c.multiple,r.$iconCheckmark=c.iconCheckmark,r.$activate=function(e){r.$$postDigest(function(){l.activate(e)})},r.$select=function(e){r.$$postDigest(function(){l.select(e)})},r.$isVisible=function(){return l.$isVisible()},r.$isActive=function(e){return l.$isActive(e)},l.update=function(e){r.$matches=e,l.$updateActiveIndex()},l.activate=function(e){return c.multiple?(r.$activeIndex.sort(),l.$isActive(e)?r.$activeIndex.splice(r.$activeIndex.indexOf(e),1):r.$activeIndex.push(e),c.sort&&r.$activeIndex.sort()):r.$activeIndex=e,r.$activeIndex},l.select=function(e){var t=r.$matches[e].value;r.$apply(function(){l.activate(e),c.multiple?n.$setViewValue(r.$activeIndex.map(function(e){return r.$matches[e].value})):(n.$setViewValue(t),l.hide())}),r.$emit("$select.select",t,e)},l.$updateActiveIndex=function(){n.$modelValue&&r.$matches.length?r.$activeIndex=c.multiple&&angular.isArray(n.$modelValue)?n.$modelValue.map(function(e){return l.$getIndex(e)}):l.$getIndex(n.$modelValue):r.$activeIndex>=r.$matches.length&&(r.$activeIndex=c.multiple?[]:0)},l.$isVisible=function(){return c.minLength&&n?r.$matches.length&&n.$viewValue.length>=c.minLength:r.$matches.length},l.$isActive=function(e){return c.multiple?-1!==r.$activeIndex.indexOf(e):r.$activeIndex===e},l.$getIndex=function(e){var t=r.$matches.length,n=t;if(t){for(n=t;n--&&r.$matches[n].value!==e;);if(!(0>n))return n}},l.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),o){var t=angular.element(e.target);t.triggerHandler("click")}},l.$onKeyDown=function(e){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!c.multiple&&(13===e.keyCode||9===e.keyCode))return l.select(r.$activeIndex);38===e.keyCode&&r.$activeIndex>0?r.$activeIndex--:40===e.keyCode&&r.$activeIndex<r.$matches.length-1?r.$activeIndex++:angular.isUndefined(r.$activeIndex)&&(r.$activeIndex=0),r.$digest()}};var u=l.show;l.show=function(){u(),c.multiple&&l.$element.addClass("select-multiple"),setTimeout(function(){l.$element.on(o?"touchstart":"mousedown",l.$onMouseDown),c.keyboard&&t.on("keydown",l.$onKeyDown)})};var s=l.hide;return l.hide=function(){l.$element.off(o?"touchstart":"mousedown",l.$onMouseDown),c.keyboard&&t.off("keydown",l.$onKeyDown),s(!0)},l}var o=(angular.element(t.document.body),"createTouch"in t.document);return l.defaults=e,l}]}).directive("bsSelect",["$window","$parse","$q","$select","$parseOptions",function(e,t,n,a,i){var l=a.defaults;return{restrict:"EAC",require:"ngModel",link:function(e,t,n,o){var c={scope:e};if(angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","placeholder","multiple","maxLength","maxLengthHtml"],function(e){angular.isDefined(n[e])&&(c[e]=n[e])}),"select"===t[0].nodeName.toLowerCase()){var r=t;r.css("display","none"),t=angular.element('<button type="button" class="btn btn-default"></button>'),r.after(t)}var u=i(n.ngOptions),s=a(t,o,c),$=u.$match[7].replace(/\|.+/,"").trim();e.$watch($,function(){u.valuesFn(e,o).then(function(e){s.update(e),o.$render()})},!0),e.$watch(n.ngModel,function(){s.$updateActiveIndex(),o.$render()},!0),o.$render=function(){var e,a;c.multiple&&angular.isArray(o.$modelValue)?(e=o.$modelValue.map(function(e){return a=s.$getIndex(e),angular.isDefined(a)?s.$scope.$matches[a].label:!1}).filter(angular.isDefined),e=e.length>(c.maxLength||l.maxLength)?e.length+" "+(c.maxLengthHtml||l.maxLengthHtml):e.join(", ")):(a=s.$getIndex(o.$modelValue),e=angular.isDefined(a)?s.$scope.$matches[a].label:!1),t.html((e?e:n.placeholder||l.placeholder)+l.caretHtml)},e.$on("$destroy",function(){s.destroy(),c=null,s=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.select').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('select/select.tpl.html', '<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><span ng-bind="match.label"></span> <i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i></a></li></ul>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(e){e.put("select/select.tpl.html",'<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><span ng-bind="match.label"></span> <i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i></a></li></ul>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.tab', []).run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('$pane', '{{pane.content}}'); |
| | | } |
| | | ]).provider('$tab', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | template: 'tab/tab.tpl.html' |
| | | }; |
| | | this.$get = function () { |
| | | return { defaults: defaults }; |
| | | }; |
| | | }).directive('bsTabs', [ |
| | | '$window', |
| | | '$animate', |
| | | '$tab', |
| | | function ($window, $animate, $tab) { |
| | | var defaults = $tab.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | require: '?ngModel', |
| | | templateUrl: function (element, attr) { |
| | | return attr.template || defaults.template; |
| | | }, |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = defaults; |
| | | angular.forEach(['animation'], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Require scope as an object |
| | | attr.bsTabs && scope.$watch(attr.bsTabs, function (newValue, oldValue) { |
| | | scope.panes = newValue; |
| | | }, true); |
| | | // Add base class |
| | | element.addClass('tabs'); |
| | | // Support animations |
| | | if (options.animation) { |
| | | element.addClass(options.animation); |
| | | } |
| | | scope.active = scope.activePane = 0; |
| | | // view -> model |
| | | scope.setActive = function (index, ev) { |
| | | scope.active = index; |
| | | if (controller) { |
| | | controller.$setViewValue(index); |
| | | } |
| | | }; |
| | | // model -> view |
| | | if (controller) { |
| | | controller.$render = function () { |
| | | scope.active = controller.$modelValue * 1; |
| | | }; |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.tab",[]).run(["$templateCache",function(t){t.put("$pane","{{pane.content}}")}]).provider("$tab",function(){var t=this.defaults={animation:"am-fade",template:"tab/tab.tpl.html"};this.$get=function(){return{defaults:t}}}).directive("bsTabs",["$window","$animate","$tab",function(t,a,e){var n=e.defaults;return{restrict:"EAC",scope:!0,require:"?ngModel",templateUrl:function(t,a){return a.template||n.template},link:function(t,a,e,i){var r=n;angular.forEach(["animation"],function(t){angular.isDefined(e[t])&&(r[t]=e[t])}),e.bsTabs&&t.$watch(e.bsTabs,function(a){t.panes=a},!0),a.addClass("tabs"),r.animation&&a.addClass(r.animation),t.active=t.activePane=0,t.setActive=function(a){t.active=a,i&&i.$setViewValue(a)},i&&(i.$render=function(){t.active=1*i.$modelValue})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.tab').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('tab/tab.tpl.html', '<ul class="nav nav-tabs"><li ng-repeat="pane in panes" ng-class="{active: $index == active}"><a data-toggle="tab" ng-click="setActive($index, $event)" data-index="{{$index}}" ng-bind-html="pane.title"></a></li></ul><div class="tab-content"><div ng-repeat="pane in panes" class="tab-pane" ng-class="[$index == active ? \'active\' : \'\']" ng-include="pane.template || \'$pane\'"></div></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(a){a.put("tab/tab.tpl.html",'<ul class="nav nav-tabs"><li ng-repeat="pane in panes" ng-class="{active: $index == active}"><a data-toggle="tab" ng-click="setActive($index, $event)" data-index="{{$index}}" ng-bind-html="pane.title"></a></li></ul><div class="tab-content"><div ng-repeat="pane in panes" class="tab-pane" ng-class="[$index == active ? \'active\' : \'\']" ng-include="pane.template || \'$pane\'"></div></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.timepicker', [ |
| | | 'mgcrea.ngStrap.helpers.dateParser', |
| | | 'mgcrea.ngStrap.tooltip' |
| | | ]).provider('$timepicker', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'timepicker', |
| | | placement: 'bottom-left', |
| | | template: 'timepicker/timepicker.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | useNative: true, |
| | | timeType: 'date', |
| | | timeFormat: 'shortTime', |
| | | modelTimeFormat: null, |
| | | autoclose: false, |
| | | minTime: -Infinity, |
| | | maxTime: +Infinity, |
| | | length: 5, |
| | | hourStep: 1, |
| | | minuteStep: 5, |
| | | iconUp: 'glyphicon glyphicon-chevron-up', |
| | | iconDown: 'glyphicon glyphicon-chevron-down' |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$document', |
| | | '$rootScope', |
| | | '$sce', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$tooltip', |
| | | function ($window, $document, $rootScope, $sce, $locale, dateFilter, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | if (!defaults.lang) |
| | | defaults.lang = $locale.id; |
| | | function timepickerFactory(element, controller, config) { |
| | | var $timepicker = $tooltip(element, angular.extend({}, defaults, config)); |
| | | var parentScope = config.scope; |
| | | var options = $timepicker.$options; |
| | | var scope = $timepicker.$scope; |
| | | // View vars |
| | | var selectedIndex = 0; |
| | | var startDate = controller.$dateValue || new Date(); |
| | | var viewDate = { |
| | | hour: startDate.getHours(), |
| | | meridian: startDate.getHours() < 12, |
| | | minute: startDate.getMinutes(), |
| | | second: startDate.getSeconds(), |
| | | millisecond: startDate.getMilliseconds() |
| | | }; |
| | | var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat; |
| | | var formats = /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1); |
| | | scope.$iconUp = options.iconUp; |
| | | scope.$iconDown = options.iconDown; |
| | | // Scope methods |
| | | scope.$select = function (date, index) { |
| | | $timepicker.select(date, index); |
| | | }; |
| | | scope.$moveIndex = function (value, index) { |
| | | $timepicker.$moveIndex(value, index); |
| | | }; |
| | | scope.$switchMeridian = function (date) { |
| | | $timepicker.switchMeridian(date); |
| | | }; |
| | | // Public methods |
| | | $timepicker.update = function (date) { |
| | | // console.warn('$timepicker.update() newValue=%o', date); |
| | | if (angular.isDate(date) && !isNaN(date.getTime())) { |
| | | $timepicker.$date = date; |
| | | angular.extend(viewDate, { |
| | | hour: date.getHours(), |
| | | minute: date.getMinutes(), |
| | | second: date.getSeconds(), |
| | | millisecond: date.getMilliseconds() |
| | | }); |
| | | $timepicker.$build(); |
| | | } else if (!$timepicker.$isBuilt) { |
| | | $timepicker.$build(); |
| | | } |
| | | }; |
| | | $timepicker.select = function (date, index, keep) { |
| | | // console.warn('$timepicker.select', date, scope.$mode); |
| | | if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) |
| | | controller.$dateValue = new Date(1970, 0, 1); |
| | | if (!angular.isDate(date)) |
| | | date = new Date(date); |
| | | if (index === 0) |
| | | controller.$dateValue.setHours(date.getHours()); |
| | | else if (index === 1) |
| | | controller.$dateValue.setMinutes(date.getMinutes()); |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | if (options.autoclose && !keep) { |
| | | $timepicker.hide(true); |
| | | } |
| | | }; |
| | | $timepicker.switchMeridian = function (date) { |
| | | var hours = (date || controller.$dateValue).getHours(); |
| | | controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12); |
| | | controller.$setViewValue(controller.$dateValue); |
| | | controller.$render(); |
| | | }; |
| | | // Protected methods |
| | | $timepicker.$build = function () { |
| | | // console.warn('$timepicker.$build() viewDate=%o', viewDate); |
| | | var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10); |
| | | var hours = [], hour; |
| | | for (i = 0; i < options.length; i++) { |
| | | hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep); |
| | | hours.push({ |
| | | date: hour, |
| | | label: dateFilter(hour, formats[0]), |
| | | selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), |
| | | disabled: $timepicker.$isDisabled(hour, 0) |
| | | }); |
| | | } |
| | | var minutes = [], minute; |
| | | for (i = 0; i < options.length; i++) { |
| | | minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep); |
| | | minutes.push({ |
| | | date: minute, |
| | | label: dateFilter(minute, formats[2]), |
| | | selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), |
| | | disabled: $timepicker.$isDisabled(minute, 1) |
| | | }); |
| | | } |
| | | var rows = []; |
| | | for (i = 0; i < options.length; i++) { |
| | | rows.push([ |
| | | hours[i], |
| | | minutes[i] |
| | | ]); |
| | | } |
| | | scope.rows = rows; |
| | | scope.showAM = !!formats[3]; |
| | | scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12; |
| | | scope.timeSeparator = formats[1]; |
| | | $timepicker.$isBuilt = true; |
| | | }; |
| | | $timepicker.$isSelected = function (date, index) { |
| | | if (!$timepicker.$date) |
| | | return false; |
| | | else if (index === 0) { |
| | | return date.getHours() === $timepicker.$date.getHours(); |
| | | } else if (index === 1) { |
| | | return date.getMinutes() === $timepicker.$date.getMinutes(); |
| | | } |
| | | }; |
| | | $timepicker.$isDisabled = function (date, index) { |
| | | var selectedTime; |
| | | if (index === 0) { |
| | | selectedTime = date.getTime() + viewDate.minute * 60000; |
| | | } else if (index === 1) { |
| | | selectedTime = date.getTime() + viewDate.hour * 3600000; |
| | | } |
| | | return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1; |
| | | }; |
| | | $timepicker.$moveIndex = function (value, index) { |
| | | var targetDate; |
| | | if (index === 0) { |
| | | targetDate = new Date(1970, 0, 1, viewDate.hour + value * options.length, viewDate.minute); |
| | | angular.extend(viewDate, { hour: targetDate.getHours() }); |
| | | } else if (index === 1) { |
| | | targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + value * options.length * options.minuteStep); |
| | | angular.extend(viewDate, { minute: targetDate.getMinutes() }); |
| | | } |
| | | $timepicker.$build(); |
| | | }; |
| | | $timepicker.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown on .dropdown-menu |
| | | if (evt.target.nodeName.toLowerCase() !== 'input') |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Emulate click for mobile devices |
| | | if (isTouch) { |
| | | var targetEl = angular.element(evt.target); |
| | | if (targetEl[0].nodeName.toLowerCase() !== 'button') { |
| | | targetEl = targetEl.parent(); |
| | | } |
| | | targetEl.triggerHandler('click'); |
| | | } |
| | | }; |
| | | $timepicker.$onKeyDown = function (evt) { |
| | | if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Close on enter |
| | | if (evt.keyCode === 13) |
| | | return $timepicker.hide(true); |
| | | // Navigate with keyboard |
| | | var newDate = new Date($timepicker.$date); |
| | | var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length; |
| | | var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length; |
| | | var lateralMove = /(37|39)/.test(evt.keyCode); |
| | | var count = 2 + !!formats[3] * 1; |
| | | // Navigate indexes (left, right) |
| | | if (lateralMove) { |
| | | if (evt.keyCode === 37) |
| | | selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1; |
| | | else if (evt.keyCode === 39) |
| | | selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0; |
| | | } |
| | | // Update values (up, down) |
| | | var selectRange = [ |
| | | 0, |
| | | hoursLength |
| | | ]; |
| | | if (selectedIndex === 0) { |
| | | if (evt.keyCode === 38) |
| | | newDate.setHours(hours - parseInt(options.hourStep, 10)); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setHours(hours + parseInt(options.hourStep, 10)); |
| | | selectRange = [ |
| | | 0, |
| | | hoursLength |
| | | ]; |
| | | } else if (selectedIndex === 1) { |
| | | if (evt.keyCode === 38) |
| | | newDate.setMinutes(minutes - parseInt(options.minuteStep, 10)); |
| | | else if (evt.keyCode === 40) |
| | | newDate.setMinutes(minutes + parseInt(options.minuteStep, 10)); |
| | | selectRange = [ |
| | | hoursLength + 1, |
| | | hoursLength + 1 + minutesLength |
| | | ]; |
| | | } else if (selectedIndex === 2) { |
| | | if (!lateralMove) |
| | | $timepicker.switchMeridian(); |
| | | selectRange = [ |
| | | hoursLength + 1 + minutesLength + 1, |
| | | hoursLength + 1 + minutesLength + 3 |
| | | ]; |
| | | } |
| | | $timepicker.select(newDate, selectedIndex, true); |
| | | createSelection(selectRange[0], selectRange[1]); |
| | | parentScope.$digest(); |
| | | }; |
| | | // Private |
| | | function createSelection(start, end) { |
| | | if (element[0].createTextRange) { |
| | | var selRange = element[0].createTextRange(); |
| | | selRange.collapse(true); |
| | | selRange.moveStart('character', start); |
| | | selRange.moveEnd('character', end); |
| | | selRange.select(); |
| | | } else if (element[0].setSelectionRange) { |
| | | element[0].setSelectionRange(start, end); |
| | | } else if (angular.isUndefined(element[0].selectionStart)) { |
| | | element[0].selectionStart = start; |
| | | element[0].selectionEnd = end; |
| | | } |
| | | } |
| | | function focusElement() { |
| | | element[0].focus(); |
| | | } |
| | | // Overrides |
| | | var _init = $timepicker.init; |
| | | $timepicker.init = function () { |
| | | if (isNative && options.useNative) { |
| | | element.prop('type', 'time'); |
| | | element.css('-webkit-appearance', 'textfield'); |
| | | return; |
| | | } else if (isTouch) { |
| | | element.prop('type', 'text'); |
| | | element.attr('readonly', 'true'); |
| | | element.on('click', focusElement); |
| | | } |
| | | _init(); |
| | | }; |
| | | var _destroy = $timepicker.destroy; |
| | | $timepicker.destroy = function () { |
| | | if (isNative && options.useNative) { |
| | | element.off('click', focusElement); |
| | | } |
| | | _destroy(); |
| | | }; |
| | | var _show = $timepicker.show; |
| | | $timepicker.show = function () { |
| | | _show(); |
| | | setTimeout(function () { |
| | | $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $timepicker.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var _hide = $timepicker.hide; |
| | | $timepicker.hide = function (blur) { |
| | | $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $timepicker.$onKeyDown); |
| | | } |
| | | _hide(blur); |
| | | }; |
| | | return $timepicker; |
| | | } |
| | | timepickerFactory.defaults = defaults; |
| | | return timepickerFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTimepicker', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$locale', |
| | | 'dateFilter', |
| | | '$timepicker', |
| | | '$dateParser', |
| | | '$timeout', |
| | | function ($window, $parse, $q, $locale, dateFilter, $timepicker, $dateParser, $timeout) { |
| | | var defaults = $timepicker.defaults; |
| | | var isNative = /(ip(a|o)d|iphone|android)/gi.test($window.navigator.userAgent); |
| | | var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { |
| | | scope: scope, |
| | | controller: controller |
| | | }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'autoclose', |
| | | 'timeType', |
| | | 'timeFormat', |
| | | 'modelTimeFormat', |
| | | 'useNative', |
| | | 'hourStep', |
| | | 'minuteStep', |
| | | 'length' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Initialize timepicker |
| | | if (isNative && (options.useNative || defaults.useNative)) |
| | | options.timeFormat = 'HH:mm'; |
| | | var timepicker = $timepicker(element, controller, options); |
| | | options = timepicker.$options; |
| | | // Initialize parser |
| | | var dateParser = $dateParser({ |
| | | format: options.timeFormat, |
| | | lang: options.lang |
| | | }); |
| | | // Observe attributes for changes |
| | | angular.forEach([ |
| | | 'minTime', |
| | | 'maxTime' |
| | | ], function (key) { |
| | | // console.warn('attr.$observe(%s)', key, attr[key]); |
| | | angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) { |
| | | if (newValue === 'now') { |
| | | timepicker.$options[key] = new Date().setFullYear(1970, 0, 1); |
| | | } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) { |
| | | timepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2)); |
| | | } else { |
| | | timepicker.$options[key] = dateParser.parse(newValue, new Date(1970, 0, 1, 0)); |
| | | } |
| | | !isNaN(timepicker.$options[key]) && timepicker.$build(); |
| | | }); |
| | | }); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue); |
| | | timepicker.update(controller.$dateValue); |
| | | }, true); |
| | | // viewValue -> $parsers -> modelValue |
| | | controller.$parsers.unshift(function (viewValue) { |
| | | // console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue); |
| | | // Null values should correctly reset the model value & validity |
| | | if (!viewValue) { |
| | | controller.$setValidity('date', true); |
| | | return; |
| | | } |
| | | var parsedTime = dateParser.parse(viewValue, controller.$dateValue); |
| | | if (!parsedTime || isNaN(parsedTime.getTime())) { |
| | | controller.$setValidity('date', false); |
| | | } else { |
| | | var isValid = parsedTime.getTime() >= options.minTime && parsedTime.getTime() <= options.maxTime; |
| | | controller.$setValidity('date', isValid); |
| | | // Only update the model when we have a valid date |
| | | if (isValid) |
| | | controller.$dateValue = parsedTime; |
| | | } |
| | | if (options.timeType === 'string') { |
| | | return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat); |
| | | } else if (options.timeType === 'number') { |
| | | return controller.$dateValue.getTime(); |
| | | } else if (options.timeType === 'iso') { |
| | | return controller.$dateValue.toISOString(); |
| | | } else { |
| | | return new Date(controller.$dateValue); |
| | | } |
| | | }); |
| | | // modelValue -> $formatters -> viewValue |
| | | controller.$formatters.push(function (modelValue) { |
| | | // console.warn('$formatter("%s"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue); |
| | | var date; |
| | | if (angular.isUndefined(modelValue) || modelValue === null) { |
| | | date = NaN; |
| | | } else if (angular.isDate(modelValue)) { |
| | | date = modelValue; |
| | | } else if (options.timeType === 'string') { |
| | | date = dateParser.parse(modelValue, null, options.modelTimeFormat); |
| | | } else { |
| | | date = new Date(modelValue); |
| | | } |
| | | // Setup default value? |
| | | // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5); |
| | | controller.$dateValue = date; |
| | | return controller.$dateValue; |
| | | }); |
| | | // viewValue -> element |
| | | controller.$render = function () { |
| | | // console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue); |
| | | element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.timeFormat)); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | timepicker.destroy(); |
| | | options = null; |
| | | timepicker = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.timepicker",["mgcrea.ngStrap.helpers.dateParser","mgcrea.ngStrap.tooltip"]).provider("$timepicker",function(){var e=this.defaults={animation:"am-fade",prefixClass:"timepicker",placement:"bottom-left",template:"timepicker/timepicker.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,useNative:!0,timeType:"date",timeFormat:"shortTime",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,iconUp:"glyphicon glyphicon-chevron-up",iconDown:"glyphicon glyphicon-chevron-down"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","$tooltip",function(t,n,a,i,o,r,u){function s(t,n,a){function i(e,n){if(t[0].createTextRange){var a=t[0].createTextRange();a.collapse(!0),a.moveStart("character",e),a.moveEnd("character",n),a.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,n):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=n)}function s(){t[0].focus()}var m=u(t,angular.extend({},e,a)),c=a.scope,g=m.$options,$=m.$scope,p=0,f=n.$dateValue||new Date,h={hour:f.getHours(),meridian:f.getHours()<12,minute:f.getMinutes(),second:f.getSeconds(),millisecond:f.getMilliseconds()},v=o.DATETIME_FORMATS[g.timeFormat]||g.timeFormat,w=/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(v).slice(1);$.$iconUp=g.iconUp,$.$iconDown=g.iconDown,$.$select=function(e,t){m.select(e,t)},$.$moveIndex=function(e,t){m.$moveIndex(e,t)},$.$switchMeridian=function(e){m.switchMeridian(e)},m.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(m.$date=e,angular.extend(h,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),m.$build()):m.$isBuilt||m.$build()},m.select=function(e,t,a){(!n.$dateValue||isNaN(n.$dateValue.getTime()))&&(n.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?n.$dateValue.setHours(e.getHours()):1===t&&n.$dateValue.setMinutes(e.getMinutes()),n.$setViewValue(n.$dateValue),n.$render(),g.autoclose&&!a&&m.hide(!0)},m.switchMeridian=function(e){var t=(e||n.$dateValue).getHours();n.$dateValue.setHours(12>t?t+12:t-12),n.$setViewValue(n.$dateValue),n.$render()},m.$build=function(){var e,t,n=$.midIndex=parseInt(g.length/2,10),a=[];for(e=0;e<g.length;e++)t=new Date(1970,0,1,h.hour-(n-e)*g.hourStep),a.push({date:t,label:r(t,w[0]),selected:m.$date&&m.$isSelected(t,0),disabled:m.$isDisabled(t,0)});var i,o=[];for(e=0;e<g.length;e++)i=new Date(1970,0,1,0,h.minute-(n-e)*g.minuteStep),o.push({date:i,label:r(i,w[2]),selected:m.$date&&m.$isSelected(i,1),disabled:m.$isDisabled(i,1)});var u=[];for(e=0;e<g.length;e++)u.push([a[e],o[e]]);$.rows=u,$.showAM=!!w[3],$.isAM=(m.$date||a[n].date).getHours()<12,$.timeSeparator=w[1],m.$isBuilt=!0},m.$isSelected=function(e,t){return m.$date?0===t?e.getHours()===m.$date.getHours():1===t?e.getMinutes()===m.$date.getMinutes():void 0:!1},m.$isDisabled=function(e,t){var n;return 0===t?n=e.getTime()+6e4*h.minute:1===t&&(n=e.getTime()+36e5*h.hour),n<1*g.minTime||n>1*g.maxTime},m.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,h.hour+e*g.length,h.minute),angular.extend(h,{hour:n.getHours()})):1===t&&(n=new Date(1970,0,1,h.hour,h.minute+e*g.length*g.minuteStep),angular.extend(h,{minute:n.getMinutes()})),m.$build()},m.$onMouseDown=function(e){if("input"!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),l){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},m.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return m.hide(!0);var t=new Date(m.$date),n=t.getHours(),a=r(t,"h").length,o=t.getMinutes(),u=r(t,"mm").length,s=/(37|39)/.test(e.keyCode),l=2+1*!!w[3];s&&(37===e.keyCode?p=1>p?l-1:p-1:39===e.keyCode&&(p=l-1>p?p+1:0));var d=[0,a];0===p?(38===e.keyCode?t.setHours(n-parseInt(g.hourStep,10)):40===e.keyCode&&t.setHours(n+parseInt(g.hourStep,10)),d=[0,a]):1===p?(38===e.keyCode?t.setMinutes(o-parseInt(g.minuteStep,10)):40===e.keyCode&&t.setMinutes(o+parseInt(g.minuteStep,10)),d=[a+1,a+1+u]):2===p&&(s||m.switchMeridian(),d=[a+1+u+1,a+1+u+3]),m.select(t,p,!0),i(d[0],d[1]),c.$digest()}};var y=m.init;m.init=function(){return d&&g.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(l&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",s)),void y())};var T=m.destroy;m.destroy=function(){d&&g.useNative&&t.off("click",s),T()};var D=m.show;m.show=function(){D(),setTimeout(function(){m.$element.on(l?"touchstart":"mousedown",m.$onMouseDown),g.keyboard&&t.on("keydown",m.$onKeyDown)})};var S=m.hide;return m.hide=function(e){m.$element.off(l?"touchstart":"mousedown",m.$onMouseDown),g.keyboard&&t.off("keydown",m.$onKeyDown),S(e)},m}var l=(angular.element(t.document.body),"createTouch"in t.document),d=/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent);return e.lang||(e.lang=o.id),s.defaults=e,s}]}).directive("bsTimepicker",["$window","$parse","$q","$locale","dateFilter","$timepicker","$dateParser","$timeout",function(e,t,n,a,i,o,r){{var u=o.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:"EAC",require:"ngModel",link:function(e,t,n,a){var l={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","modelTimeFormat","useNative","hourStep","minuteStep","length"],function(e){angular.isDefined(n[e])&&(l[e]=n[e])}),s&&(l.useNative||u.useNative)&&(l.timeFormat="HH:mm");var d=o(t,a,l);l=d.$options;var m=r({format:l.timeFormat,lang:l.lang});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){d.$options[e]="now"===t?(new Date).setFullYear(1970,0,1):angular.isString(t)&&t.match(/^".+"$/)?+new Date(t.substr(1,t.length-2)):m.parse(t,new Date(1970,0,1,0)),!isNaN(d.$options[e])&&d.$build()})}),e.$watch(n.ngModel,function(){d.update(a.$dateValue)},!0),a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=m.parse(e,a.$dateValue);if(!t||isNaN(t.getTime()))a.$setValidity("date",!1);else{var n=t.getTime()>=l.minTime&&t.getTime()<=l.maxTime;a.$setValidity("date",n),n&&(a.$dateValue=t)}return"string"===l.timeType?i(t,l.modelTimeFormat||l.timeFormat):"number"===l.timeType?a.$dateValue.getTime():"iso"===l.timeType?a.$dateValue.toISOString():new Date(a.$dateValue)}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===l.timeType?m.parse(e,null,l.modelTimeFormat):new Date(e),a.$dateValue=t,a.$dateValue}),a.$render=function(){t.val(!a.$dateValue||isNaN(a.$dateValue.getTime())?"":i(a.$dateValue,l.timeFormat))},e.$on("$destroy",function(){d.destroy(),l=null,d=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.timepicker').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('timepicker/timepicker.tpl.html', '<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 0)"><i class="{{$iconUp}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 1)"><i class="{{$iconUp}}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td ng-if="showAM"> </td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 0)"><i class="{{$iconDown}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 1)"><i class="{{$iconDown}}"></i></button></th></tr></tfoot></table></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.timepicker").run(["$templateCache",function(t){t.put("timepicker/timepicker.tpl.html",'<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 0)"><i class="{{$iconUp}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(-1, 1)"><i class="{{$iconUp}}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td ng-if="showAM"> </td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 0)"><i class="{{$iconDown}}"></i></button></th><th> </th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$moveIndex(1, 1)"><i class="{{$iconDown}}"></i></button></th></tr></tfoot></table></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'tooltip', |
| | | prefixEvent: 'tooltip', |
| | | container: false, |
| | | target: false, |
| | | placement: 'top', |
| | | template: 'tooltip/tooltip.tpl.html', |
| | | contentTemplate: false, |
| | | trigger: 'hover focus', |
| | | keyboard: false, |
| | | html: false, |
| | | show: false, |
| | | title: '', |
| | | type: '', |
| | | delay: 0 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$compile', |
| | | '$q', |
| | | '$templateCache', |
| | | '$http', |
| | | '$animate', |
| | | 'dimensions', |
| | | '$$rAF', |
| | | function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, dimensions, $$rAF) { |
| | | var trim = String.prototype.trim; |
| | | var isTouch = 'createTouch' in $window.document; |
| | | var htmlReplaceRegExp = /ng-bind="/gi; |
| | | function TooltipFactory(element, config) { |
| | | var $tooltip = {}; |
| | | // Common vars |
| | | var nodeName = element[0].nodeName.toLowerCase(); |
| | | var options = $tooltip.$options = angular.extend({}, defaults, config); |
| | | $tooltip.$promise = fetchTemplate(options.template); |
| | | var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new(); |
| | | if (options.delay && angular.isString(options.delay)) { |
| | | options.delay = parseFloat(options.delay); |
| | | } |
| | | // Support scope as string options |
| | | if (options.title) { |
| | | $tooltip.$scope.title = options.title; |
| | | } |
| | | // Provide scope helpers |
| | | scope.$hide = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.hide(); |
| | | }); |
| | | }; |
| | | scope.$show = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.show(); |
| | | }); |
| | | }; |
| | | scope.$toggle = function () { |
| | | scope.$$postDigest(function () { |
| | | $tooltip.toggle(); |
| | | }); |
| | | }; |
| | | $tooltip.$isShown = scope.$isShown = false; |
| | | // Private vars |
| | | var timeout, hoverState; |
| | | // Support contentTemplate option |
| | | if (options.contentTemplate) { |
| | | $tooltip.$promise = $tooltip.$promise.then(function (template) { |
| | | var templateEl = angular.element(template); |
| | | return fetchTemplate(options.contentTemplate).then(function (contentTemplate) { |
| | | var contentEl = findElement('[ng-bind="content"]', templateEl[0]); |
| | | if (!contentEl.length) |
| | | contentEl = findElement('[ng-bind="title"]', templateEl[0]); |
| | | contentEl.removeAttr('ng-bind').html(contentTemplate); |
| | | return templateEl[0].outerHTML; |
| | | }); |
| | | }); |
| | | } |
| | | // Fetch, compile then initialize tooltip |
| | | var tipLinker, tipElement, tipTemplate, tipContainer; |
| | | $tooltip.$promise.then(function (template) { |
| | | if (angular.isObject(template)) |
| | | template = template.data; |
| | | if (options.html) |
| | | template = template.replace(htmlReplaceRegExp, 'ng-bind-html="'); |
| | | template = trim.apply(template); |
| | | tipTemplate = template; |
| | | tipLinker = $compile(template); |
| | | $tooltip.init(); |
| | | }); |
| | | $tooltip.init = function () { |
| | | // Options: delay |
| | | if (options.delay && angular.isNumber(options.delay)) { |
| | | options.delay = { |
| | | show: options.delay, |
| | | hide: options.delay |
| | | }; |
| | | } |
| | | // Replace trigger on touch devices ? |
| | | // if(isTouch && options.trigger === defaults.trigger) { |
| | | // options.trigger.replace(/hover/g, 'click'); |
| | | // } |
| | | // Options : container |
| | | if (options.container === 'self') { |
| | | tipContainer = element; |
| | | } else if (options.container) { |
| | | tipContainer = findElement(options.container); |
| | | } |
| | | // Options: trigger |
| | | var triggers = options.trigger.split(' '); |
| | | angular.forEach(triggers, function (trigger) { |
| | | if (trigger === 'click') { |
| | | element.on('click', $tooltip.toggle); |
| | | } else if (trigger !== 'manual') { |
| | | element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter); |
| | | element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave); |
| | | nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown); |
| | | } |
| | | }); |
| | | // Options: target |
| | | if (options.target) { |
| | | options.target = angular.isElement(options.target) ? options.target : findElement(options.target)[0]; |
| | | } |
| | | // Options: show |
| | | if (options.show) { |
| | | scope.$$postDigest(function () { |
| | | options.trigger === 'focus' ? element[0].focus() : $tooltip.show(); |
| | | }); |
| | | } |
| | | }; |
| | | $tooltip.destroy = function () { |
| | | // Unbind events |
| | | var triggers = options.trigger.split(' '); |
| | | for (var i = triggers.length; i--;) { |
| | | var trigger = triggers[i]; |
| | | if (trigger === 'click') { |
| | | element.off('click', $tooltip.toggle); |
| | | } else if (trigger !== 'manual') { |
| | | element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter); |
| | | element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave); |
| | | nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown); |
| | | } |
| | | } |
| | | // Remove element |
| | | if (tipElement) { |
| | | tipElement.remove(); |
| | | tipElement = null; |
| | | } |
| | | // Cancel pending callbacks |
| | | clearTimeout(timeout); |
| | | // Destroy scope |
| | | scope.$destroy(); |
| | | }; |
| | | $tooltip.enter = function () { |
| | | clearTimeout(timeout); |
| | | hoverState = 'in'; |
| | | if (!options.delay || !options.delay.show) { |
| | | return $tooltip.show(); |
| | | } |
| | | timeout = setTimeout(function () { |
| | | if (hoverState === 'in') |
| | | $tooltip.show(); |
| | | }, options.delay.show); |
| | | }; |
| | | $tooltip.show = function () { |
| | | scope.$emit(options.prefixEvent + '.show.before', $tooltip); |
| | | var parent = options.container ? tipContainer : null; |
| | | var after = options.container ? null : element; |
| | | // Hide any existing tipElement |
| | | if (tipElement) |
| | | tipElement.remove(); |
| | | // Fetch a cloned element linked from template |
| | | tipElement = $tooltip.$element = tipLinker(scope, function (clonedElement, scope) { |
| | | }); |
| | | // Set the initial positioning. |
| | | tipElement.css({ |
| | | top: '-9999px', |
| | | left: '-9999px', |
| | | display: 'block' |
| | | }).addClass(options.placement); |
| | | // Options: animation |
| | | if (options.animation) |
| | | tipElement.addClass(options.animation); |
| | | // Options: type |
| | | if (options.type) |
| | | tipElement.addClass(options.prefixClass + '-' + options.type); |
| | | $animate.enter(tipElement, parent, after, function () { |
| | | scope.$emit(options.prefixEvent + '.show', $tooltip); |
| | | }); |
| | | $tooltip.$isShown = scope.$isShown = true; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | $$rAF($tooltip.$applyPlacement); |
| | | // var a = bodyEl.offsetWidth + 1; ? |
| | | // Bind events |
| | | if (options.keyboard) { |
| | | if (options.trigger !== 'focus') { |
| | | $tooltip.focus(); |
| | | tipElement.on('keyup', $tooltip.$onKeyUp); |
| | | } else { |
| | | element.on('keyup', $tooltip.$onFocusKeyUp); |
| | | } |
| | | } |
| | | }; |
| | | $tooltip.leave = function () { |
| | | clearTimeout(timeout); |
| | | hoverState = 'out'; |
| | | if (!options.delay || !options.delay.hide) { |
| | | return $tooltip.hide(); |
| | | } |
| | | timeout = setTimeout(function () { |
| | | if (hoverState === 'out') { |
| | | $tooltip.hide(); |
| | | } |
| | | }, options.delay.hide); |
| | | }; |
| | | $tooltip.hide = function (blur) { |
| | | if (!$tooltip.$isShown) |
| | | return; |
| | | scope.$emit(options.prefixEvent + '.hide.before', $tooltip); |
| | | $animate.leave(tipElement, function () { |
| | | scope.$emit(options.prefixEvent + '.hide', $tooltip); |
| | | }); |
| | | $tooltip.$isShown = scope.$isShown = false; |
| | | scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest(); |
| | | // Unbind events |
| | | if (options.keyboard && tipElement !== null) { |
| | | tipElement.off('keyup', $tooltip.$onKeyUp); |
| | | } |
| | | // Allow to blur the input when hidden, like when pressing enter key |
| | | if (blur && options.trigger === 'focus') { |
| | | return element[0].blur(); |
| | | } |
| | | }; |
| | | $tooltip.toggle = function () { |
| | | $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter(); |
| | | }; |
| | | $tooltip.focus = function () { |
| | | tipElement[0].focus(); |
| | | }; |
| | | // Protected methods |
| | | $tooltip.$applyPlacement = function () { |
| | | if (!tipElement) |
| | | return; |
| | | // Get the position of the tooltip element. |
| | | var elementPosition = getPosition(); |
| | | // Get the height and width of the tooltip so we can center it. |
| | | var tipWidth = tipElement.prop('offsetWidth'), tipHeight = tipElement.prop('offsetHeight'); |
| | | // Get the tooltip's top and left coordinates to center it with this directive. |
| | | var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight); |
| | | // Now set the calculated positioning. |
| | | tipPosition.top += 'px'; |
| | | tipPosition.left += 'px'; |
| | | tipElement.css(tipPosition); |
| | | }; |
| | | $tooltip.$onKeyUp = function (evt) { |
| | | evt.which === 27 && $tooltip.hide(); |
| | | }; |
| | | $tooltip.$onFocusKeyUp = function (evt) { |
| | | evt.which === 27 && element[0].blur(); |
| | | }; |
| | | $tooltip.$onFocusElementMouseDown = function (evt) { |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Some browsers do not auto-focus buttons (eg. Safari) |
| | | $tooltip.$isShown ? element[0].blur() : element[0].focus(); |
| | | }; |
| | | // Private methods |
| | | function getPosition() { |
| | | if (options.container === 'body') { |
| | | return dimensions.offset(options.target || element[0]); |
| | | } else { |
| | | return dimensions.position(options.target || element[0]); |
| | | } |
| | | } |
| | | function getCalculatedOffset(placement, position, actualWidth, actualHeight) { |
| | | var offset; |
| | | var split = placement.split('-'); |
| | | switch (split[0]) { |
| | | case 'right': |
| | | offset = { |
| | | top: position.top + position.height / 2 - actualHeight / 2, |
| | | left: position.left + position.width |
| | | }; |
| | | break; |
| | | case 'bottom': |
| | | offset = { |
| | | top: position.top + position.height, |
| | | left: position.left + position.width / 2 - actualWidth / 2 |
| | | }; |
| | | break; |
| | | case 'left': |
| | | offset = { |
| | | top: position.top + position.height / 2 - actualHeight / 2, |
| | | left: position.left - actualWidth |
| | | }; |
| | | break; |
| | | default: |
| | | offset = { |
| | | top: position.top - actualHeight, |
| | | left: position.left + position.width / 2 - actualWidth / 2 |
| | | }; |
| | | break; |
| | | } |
| | | if (!split[1]) { |
| | | return offset; |
| | | } |
| | | // Add support for corners @todo css |
| | | if (split[0] === 'top' || split[0] === 'bottom') { |
| | | switch (split[1]) { |
| | | case 'left': |
| | | offset.left = position.left; |
| | | break; |
| | | case 'right': |
| | | offset.left = position.left + position.width - actualWidth; |
| | | } |
| | | } else if (split[0] === 'left' || split[0] === 'right') { |
| | | switch (split[1]) { |
| | | case 'top': |
| | | offset.top = position.top - actualHeight; |
| | | break; |
| | | case 'bottom': |
| | | offset.top = position.top + position.height; |
| | | } |
| | | } |
| | | return offset; |
| | | } |
| | | return $tooltip; |
| | | } |
| | | // Helper functions |
| | | function findElement(query, element) { |
| | | return angular.element((element || document).querySelectorAll(query)); |
| | | } |
| | | function fetchTemplate(template) { |
| | | return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) { |
| | | if (angular.isObject(res)) { |
| | | $templateCache.put(template, res.data); |
| | | return res.data; |
| | | } |
| | | return res; |
| | | }); |
| | | } |
| | | return TooltipFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTooltip', [ |
| | | '$window', |
| | | '$location', |
| | | '$sce', |
| | | '$tooltip', |
| | | '$$rAF', |
| | | function ($window, $location, $sce, $tooltip, $$rAF) { |
| | | return { |
| | | restrict: 'EAC', |
| | | scope: true, |
| | | link: function postLink(scope, element, attr, transclusion) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'template', |
| | | 'contentTemplate', |
| | | 'placement', |
| | | 'container', |
| | | 'target', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'type' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Observe scope attributes for change |
| | | angular.forEach(['title'], function (key) { |
| | | attr[key] && attr.$observe(key, function (newValue, oldValue) { |
| | | scope[key] = $sce.trustAsHtml(newValue); |
| | | angular.isDefined(oldValue) && $$rAF(function () { |
| | | tooltip && tooltip.$applyPlacement(); |
| | | }); |
| | | }); |
| | | }); |
| | | // Support scope as an object |
| | | attr.bsTooltip && scope.$watch(attr.bsTooltip, function (newValue, oldValue) { |
| | | if (angular.isObject(newValue)) { |
| | | angular.extend(scope, newValue); |
| | | } else { |
| | | scope.title = newValue; |
| | | } |
| | | angular.isDefined(oldValue) && $$rAF(function () { |
| | | tooltip && tooltip.$applyPlacement(); |
| | | }); |
| | | }, true); |
| | | // Initialize popover |
| | | var tooltip = $tooltip(element, options); |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | tooltip.destroy(); |
| | | options = null; |
| | | tooltip = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.helpers.dimensions"]).provider("$tooltip",function(){var e=this.defaults={animation:"am-fade",prefixClass:"tooltip",prefixEvent:"tooltip",container:!1,target:!1,placement:"top",template:"tooltip/tooltip.tpl.html",contentTemplate:!1,trigger:"hover focus",keyboard:!1,html:!1,show:!1,title:"",type:"",delay:0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","dimensions","$$rAF",function(t,o,n,i,a,r,l,s,u){function c(t,i){function a(){return"body"===m.container?s.offset(m.target||t[0]):s.position(m.target||t[0])}function r(e,t,o,n){var i,a=e.split("-");switch(a[0]){case"right":i={top:t.top+t.height/2-n/2,left:t.left+t.width};break;case"bottom":i={top:t.top+t.height,left:t.left+t.width/2-o/2};break;case"left":i={top:t.top+t.height/2-n/2,left:t.left-o};break;default:i={top:t.top-n,left:t.left+t.width/2-o/2}}if(!a[1])return i;if("top"===a[0]||"bottom"===a[0])switch(a[1]){case"left":i.left=t.left;break;case"right":i.left=t.left+t.width-o}else if("left"===a[0]||"right"===a[0])switch(a[1]){case"top":i.top=t.top-n;break;case"bottom":i.top=t.top+t.height}return i}var c={},$=t[0].nodeName.toLowerCase(),m=c.$options=angular.extend({},e,i);c.$promise=f(m.template);var v=c.$scope=m.scope&&m.scope.$new()||o.$new();m.delay&&angular.isString(m.delay)&&(m.delay=parseFloat(m.delay)),m.title&&(c.$scope.title=m.title),v.$hide=function(){v.$$postDigest(function(){c.hide()})},v.$show=function(){v.$$postDigest(function(){c.show()})},v.$toggle=function(){v.$$postDigest(function(){c.toggle()})},c.$isShown=v.$isShown=!1;var y,w;m.contentTemplate&&(c.$promise=c.$promise.then(function(e){var t=angular.element(e);return f(m.contentTemplate).then(function(e){var o=p('[ng-bind="content"]',t[0]);return o.length||(o=p('[ng-bind="title"]',t[0])),o.removeAttr("ng-bind").html(e),t[0].outerHTML})}));var b,k,S,T;return c.$promise.then(function(e){angular.isObject(e)&&(e=e.data),m.html&&(e=e.replace(g,'ng-bind-html="')),e=h.apply(e),S=e,b=n(e),c.init()}),c.init=function(){m.delay&&angular.isNumber(m.delay)&&(m.delay={show:m.delay,hide:m.delay}),"self"===m.container?T=t:m.container&&(T=p(m.container));var e=m.trigger.split(" ");angular.forEach(e,function(e){"click"===e?t.on("click",c.toggle):"manual"!==e&&(t.on("hover"===e?"mouseenter":"focus",c.enter),t.on("hover"===e?"mouseleave":"blur",c.leave),"button"===$&&"hover"!==e&&t.on(d?"touchstart":"mousedown",c.$onFocusElementMouseDown))}),m.target&&(m.target=angular.isElement(m.target)?m.target:p(m.target)[0]),m.show&&v.$$postDigest(function(){"focus"===m.trigger?t[0].focus():c.show()})},c.destroy=function(){for(var e=m.trigger.split(" "),o=e.length;o--;){var n=e[o];"click"===n?t.off("click",c.toggle):"manual"!==n&&(t.off("hover"===n?"mouseenter":"focus",c.enter),t.off("hover"===n?"mouseleave":"blur",c.leave),"button"===$&&"hover"!==n&&t.off(d?"touchstart":"mousedown",c.$onFocusElementMouseDown))}k&&(k.remove(),k=null),clearTimeout(y),v.$destroy()},c.enter=function(){return clearTimeout(y),w="in",m.delay&&m.delay.show?void(y=setTimeout(function(){"in"===w&&c.show()},m.delay.show)):c.show()},c.show=function(){v.$emit(m.prefixEvent+".show.before",c);var e=m.container?T:null,o=m.container?null:t;k&&k.remove(),k=c.$element=b(v,function(){}),k.css({top:"-9999px",left:"-9999px",display:"block"}).addClass(m.placement),m.animation&&k.addClass(m.animation),m.type&&k.addClass(m.prefixClass+"-"+m.type),l.enter(k,e,o,function(){v.$emit(m.prefixEvent+".show",c)}),c.$isShown=v.$isShown=!0,v.$$phase||v.$root&&v.$root.$$phase||v.$digest(),u(c.$applyPlacement),m.keyboard&&("focus"!==m.trigger?(c.focus(),k.on("keyup",c.$onKeyUp)):t.on("keyup",c.$onFocusKeyUp))},c.leave=function(){return clearTimeout(y),w="out",m.delay&&m.delay.hide?void(y=setTimeout(function(){"out"===w&&c.hide()},m.delay.hide)):c.hide()},c.hide=function(e){return c.$isShown?(v.$emit(m.prefixEvent+".hide.before",c),l.leave(k,function(){v.$emit(m.prefixEvent+".hide",c)}),c.$isShown=v.$isShown=!1,v.$$phase||v.$root&&v.$root.$$phase||v.$digest(),m.keyboard&&null!==k&&k.off("keyup",c.$onKeyUp),e&&"focus"===m.trigger?t[0].blur():void 0):void 0},c.toggle=function(){c.$isShown?c.leave():c.enter()},c.focus=function(){k[0].focus()},c.$applyPlacement=function(){if(k){var e=a(),t=k.prop("offsetWidth"),o=k.prop("offsetHeight"),n=r(m.placement,e,t,o);n.top+="px",n.left+="px",k.css(n)}},c.$onKeyUp=function(e){27===e.which&&c.hide()},c.$onFocusKeyUp=function(e){27===e.which&&t[0].blur()},c.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),c.$isShown?t[0].blur():t[0].focus()},c}function p(e,t){return angular.element((t||document).querySelectorAll(e))}function f(e){return i.when(a.get(e)||r.get(e)).then(function(t){return angular.isObject(t)?(a.put(e,t.data),t.data):t})}var h=String.prototype.trim,d="createTouch"in t.document,g=/ng-bind="/gi;return c}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip","$$rAF",function(e,t,o,n,i){return{restrict:"EAC",scope:!0,link:function(e,t,a){var r={scope:e};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type"],function(e){angular.isDefined(a[e])&&(r[e]=a[e])}),angular.forEach(["title"],function(t){a[t]&&a.$observe(t,function(n,a){e[t]=o.trustAsHtml(n),angular.isDefined(a)&&i(function(){l&&l.$applyPlacement()})})}),a.bsTooltip&&e.$watch(a.bsTooltip,function(t,o){angular.isObject(t)?angular.extend(e,t):e.title=t,angular.isDefined(o)&&i(function(){l&&l.$applyPlacement()})},!0);var l=n(t,r);e.$on("$destroy",function(){l.destroy(),r=null,l=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.tooltip').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('tooltip/tooltip.tpl.html', '<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.tooltip").run(["$templateCache",function(t){t.put("tooltip/tooltip.tpl.html",'<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>')}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.typeahead', [ |
| | | 'mgcrea.ngStrap.tooltip', |
| | | 'mgcrea.ngStrap.helpers.parseOptions' |
| | | ]).provider('$typeahead', function () { |
| | | var defaults = this.defaults = { |
| | | animation: 'am-fade', |
| | | prefixClass: 'typeahead', |
| | | placement: 'bottom-left', |
| | | template: 'typeahead/typeahead.tpl.html', |
| | | trigger: 'focus', |
| | | container: false, |
| | | keyboard: true, |
| | | html: false, |
| | | delay: 0, |
| | | minLength: 1, |
| | | filter: 'filter', |
| | | limit: 6 |
| | | }; |
| | | this.$get = [ |
| | | '$window', |
| | | '$rootScope', |
| | | '$tooltip', |
| | | function ($window, $rootScope, $tooltip) { |
| | | var bodyEl = angular.element($window.document.body); |
| | | function TypeaheadFactory(element, controller, config) { |
| | | var $typeahead = {}; |
| | | // Common vars |
| | | var options = angular.extend({}, defaults, config); |
| | | $typeahead = $tooltip(element, options); |
| | | var parentScope = config.scope; |
| | | var scope = $typeahead.$scope; |
| | | scope.$resetMatches = function () { |
| | | scope.$matches = []; |
| | | scope.$activeIndex = 0; |
| | | }; |
| | | scope.$resetMatches(); |
| | | scope.$activate = function (index) { |
| | | scope.$$postDigest(function () { |
| | | $typeahead.activate(index); |
| | | }); |
| | | }; |
| | | scope.$select = function (index, evt) { |
| | | scope.$$postDigest(function () { |
| | | $typeahead.select(index); |
| | | }); |
| | | }; |
| | | scope.$isVisible = function () { |
| | | return $typeahead.$isVisible(); |
| | | }; |
| | | // Public methods |
| | | $typeahead.update = function (matches) { |
| | | scope.$matches = matches; |
| | | if (scope.$activeIndex >= matches.length) { |
| | | scope.$activeIndex = 0; |
| | | } |
| | | }; |
| | | $typeahead.activate = function (index) { |
| | | scope.$activeIndex = index; |
| | | }; |
| | | $typeahead.select = function (index) { |
| | | var value = scope.$matches[index].value; |
| | | controller.$setViewValue(value); |
| | | controller.$render(); |
| | | scope.$resetMatches(); |
| | | if (parentScope) |
| | | parentScope.$digest(); |
| | | // Emit event |
| | | scope.$emit('$typeahead.select', value, index); |
| | | }; |
| | | // Protected methods |
| | | $typeahead.$isVisible = function () { |
| | | if (!options.minLength || !controller) { |
| | | return !!scope.$matches.length; |
| | | } |
| | | // minLength support |
| | | return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength; |
| | | }; |
| | | $typeahead.$getIndex = function (value) { |
| | | var l = scope.$matches.length, i = l; |
| | | if (!l) |
| | | return; |
| | | for (i = l; i--;) { |
| | | if (scope.$matches[i].value === value) |
| | | break; |
| | | } |
| | | if (i < 0) |
| | | return; |
| | | return i; |
| | | }; |
| | | $typeahead.$onMouseDown = function (evt) { |
| | | // Prevent blur on mousedown |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | }; |
| | | $typeahead.$onKeyDown = function (evt) { |
| | | if (!/(38|40|13)/.test(evt.keyCode)) |
| | | return; |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | // Select with enter |
| | | if (evt.keyCode === 13 && scope.$matches.length) { |
| | | $typeahead.select(scope.$activeIndex); |
| | | } // Navigate with keyboard |
| | | else if (evt.keyCode === 38 && scope.$activeIndex > 0) |
| | | scope.$activeIndex--; |
| | | else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) |
| | | scope.$activeIndex++; |
| | | else if (angular.isUndefined(scope.$activeIndex)) |
| | | scope.$activeIndex = 0; |
| | | scope.$digest(); |
| | | }; |
| | | // Overrides |
| | | var show = $typeahead.show; |
| | | $typeahead.show = function () { |
| | | show(); |
| | | setTimeout(function () { |
| | | $typeahead.$element.on('mousedown', $typeahead.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.on('keydown', $typeahead.$onKeyDown); |
| | | } |
| | | }); |
| | | }; |
| | | var hide = $typeahead.hide; |
| | | $typeahead.hide = function () { |
| | | $typeahead.$element.off('mousedown', $typeahead.$onMouseDown); |
| | | if (options.keyboard) { |
| | | element.off('keydown', $typeahead.$onKeyDown); |
| | | } |
| | | hide(); |
| | | }; |
| | | return $typeahead; |
| | | } |
| | | TypeaheadFactory.defaults = defaults; |
| | | return TypeaheadFactory; |
| | | } |
| | | ]; |
| | | }).directive('bsTypeahead', [ |
| | | '$window', |
| | | '$parse', |
| | | '$q', |
| | | '$typeahead', |
| | | '$parseOptions', |
| | | function ($window, $parse, $q, $typeahead, $parseOptions) { |
| | | var defaults = $typeahead.defaults; |
| | | return { |
| | | restrict: 'EAC', |
| | | require: 'ngModel', |
| | | link: function postLink(scope, element, attr, controller) { |
| | | // Directive options |
| | | var options = { scope: scope }; |
| | | angular.forEach([ |
| | | 'placement', |
| | | 'container', |
| | | 'delay', |
| | | 'trigger', |
| | | 'keyboard', |
| | | 'html', |
| | | 'animation', |
| | | 'template', |
| | | 'filter', |
| | | 'limit', |
| | | 'minLength' |
| | | ], function (key) { |
| | | if (angular.isDefined(attr[key])) |
| | | options[key] = attr[key]; |
| | | }); |
| | | // Build proper ngOptions |
| | | var filter = options.filter || defaults.filter; |
| | | var limit = options.limit || defaults.limit; |
| | | var ngOptions = attr.ngOptions; |
| | | if (filter) |
| | | ngOptions += ' | ' + filter + ':$viewValue'; |
| | | if (limit) |
| | | ngOptions += ' | limitTo:' + limit; |
| | | var parsedOptions = $parseOptions(ngOptions); |
| | | // Initialize typeahead |
| | | var typeahead = $typeahead(element, controller, options); |
| | | // Watch model for changes |
| | | scope.$watch(attr.ngModel, function (newValue, oldValue) { |
| | | // console.warn('$watch', element.attr('ng-model'), newValue); |
| | | scope.$modelValue = newValue; |
| | | // Publish modelValue on scope for custom templates |
| | | parsedOptions.valuesFn(scope, controller).then(function (values) { |
| | | if (values.length > limit) |
| | | values = values.slice(0, limit); |
| | | // Do not re-queue an update if a correct value has been selected |
| | | if (values.length === 1 && values[0].value === newValue) |
| | | return; |
| | | typeahead.update(values); |
| | | // Queue a new rendering that will leverage collection loading |
| | | controller.$render(); |
| | | }); |
| | | }); |
| | | // Model rendering in view |
| | | controller.$render = function () { |
| | | // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue); |
| | | if (controller.$isEmpty(controller.$viewValue)) |
| | | return element.val(''); |
| | | var index = typeahead.$getIndex(controller.$modelValue); |
| | | var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue; |
| | | selected = angular.isObject(selected) ? selected.label : selected; |
| | | element.val(selected.replace(/<(?:.|\n)*?>/gm, '').trim()); |
| | | }; |
| | | // Garbage collection |
| | | scope.$on('$destroy', function () { |
| | | typeahead.destroy(); |
| | | options = null; |
| | | typeahead = null; |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.typeahead",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$typeahead",function(){var e=this.defaults={animation:"am-fade",prefixClass:"typeahead",placement:"bottom-left",template:"typeahead/typeahead.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,minLength:1,filter:"filter",limit:6};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function i(t,n,i){var o={},r=angular.extend({},e,i);o=a(t,r);var l=i.scope,c=o.$scope;c.$resetMatches=function(){c.$matches=[],c.$activeIndex=0},c.$resetMatches(),c.$activate=function(e){c.$$postDigest(function(){o.activate(e)})},c.$select=function(e){c.$$postDigest(function(){o.select(e)})},c.$isVisible=function(){return o.$isVisible()},o.update=function(e){c.$matches=e,c.$activeIndex>=e.length&&(c.$activeIndex=0)},o.activate=function(e){c.$activeIndex=e},o.select=function(e){var t=c.$matches[e].value;n.$setViewValue(t),n.$render(),c.$resetMatches(),l&&l.$digest(),c.$emit("$typeahead.select",t,e)},o.$isVisible=function(){return r.minLength&&n?c.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=r.minLength:!!c.$matches.length},o.$getIndex=function(e){var t=c.$matches.length,n=t;if(t){for(n=t;n--&&c.$matches[n].value!==e;);if(!(0>n))return n}},o.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},o.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(e.preventDefault(),e.stopPropagation(),13===e.keyCode&&c.$matches.length?o.select(c.$activeIndex):38===e.keyCode&&c.$activeIndex>0?c.$activeIndex--:40===e.keyCode&&c.$activeIndex<c.$matches.length-1?c.$activeIndex++:angular.isUndefined(c.$activeIndex)&&(c.$activeIndex=0),c.$digest())};var s=o.show;o.show=function(){s(),setTimeout(function(){o.$element.on("mousedown",o.$onMouseDown),r.keyboard&&t.on("keydown",o.$onKeyDown)})};var u=o.hide;return o.hide=function(){o.$element.off("mousedown",o.$onMouseDown),r.keyboard&&t.off("keydown",o.$onKeyDown),u()},o}angular.element(t.document.body);return i.defaults=e,i}]}).directive("bsTypeahead",["$window","$parse","$q","$typeahead","$parseOptions",function(e,t,n,a,i){var o=a.defaults;return{restrict:"EAC",require:"ngModel",link:function(e,t,n,r){var l={scope:e};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","filter","limit","minLength"],function(e){angular.isDefined(n[e])&&(l[e]=n[e])});var c=l.filter||o.filter,s=l.limit||o.limit,u=n.ngOptions;c&&(u+=" | "+c+":$viewValue"),s&&(u+=" | limitTo:"+s);var $=i(u),d=a(t,r,l);e.$watch(n.ngModel,function(t){e.$modelValue=t,$.valuesFn(e,r).then(function(e){e.length>s&&(e=e.slice(0,s)),(1!==e.length||e[0].value!==t)&&(d.update(e),r.$render())})}),r.$render=function(){if(r.$isEmpty(r.$viewValue))return t.val("");var e=d.$getIndex(r.$modelValue),n=angular.isDefined(e)?d.$scope.$matches[e].label:r.$viewValue;n=angular.isObject(n)?n.label:n,t.val(n.replace(/<(?:.|\n)*?>/gm,"").trim())},e.$on("$destroy",function(){d.destroy(),l=null,d=null})}}}]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | 'use strict'; |
| | | angular.module('mgcrea.ngStrap.typeahead').run([ |
| | | '$templateCache', |
| | | function ($templateCache) { |
| | | $templateCache.put('typeahead/typeahead.tpl.html', '<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>'); |
| | | } |
| | | ]); |
New file |
| | |
| | | /** |
| | | * angular-strap |
| | | * @version v2.0.3 - 2014-05-30 |
| | | * @link http://mgcrea.github.io/angular-strap |
| | | * @author Olivier Louvignes (olivier@mg-crea.com) |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "use strict";angular.module("mgcrea.ngStrap.typeahead").run(["$templateCache",function(e){e.put("typeahead/typeahead.tpl.html",'<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>')}]); |
New file |
| | |
| | | /** |
| | | * State-based routing for AngularJS |
| | | * @version v0.2.10 |
| | | * @link http://angular-ui.github.com/ |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | |
| | | /* commonjs package manager support (eg componentjs) */ |
| | | if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){ |
| | | module.exports = 'ui.router'; |
| | | } |
| | | |
| | | (function (window, angular, undefined) { |
| | | /*jshint globalstrict:true*/ |
| | | /*global angular:false*/ |
| | | 'use strict'; |
| | | |
| | | var isDefined = angular.isDefined, |
| | | isFunction = angular.isFunction, |
| | | isString = angular.isString, |
| | | isObject = angular.isObject, |
| | | isArray = angular.isArray, |
| | | forEach = angular.forEach, |
| | | extend = angular.extend, |
| | | copy = angular.copy; |
| | | |
| | | function inherit(parent, extra) { |
| | | return extend(new (extend(function() {}, { prototype: parent }))(), extra); |
| | | } |
| | | |
| | | function merge(dst) { |
| | | forEach(arguments, function(obj) { |
| | | if (obj !== dst) { |
| | | forEach(obj, function(value, key) { |
| | | if (!dst.hasOwnProperty(key)) dst[key] = value; |
| | | }); |
| | | } |
| | | }); |
| | | return dst; |
| | | } |
| | | |
| | | /** |
| | | * Finds the common ancestor path between two states. |
| | | * |
| | | * @param {Object} first The first state. |
| | | * @param {Object} second The second state. |
| | | * @return {Array} Returns an array of state names in descending order, not including the root. |
| | | */ |
| | | function ancestors(first, second) { |
| | | var path = []; |
| | | |
| | | for (var n in first.path) { |
| | | if (first.path[n] !== second.path[n]) break; |
| | | path.push(first.path[n]); |
| | | } |
| | | return path; |
| | | } |
| | | |
| | | /** |
| | | * IE8-safe wrapper for `Object.keys()`. |
| | | * |
| | | * @param {Object} object A JavaScript object. |
| | | * @return {Array} Returns the keys of the object as an array. |
| | | */ |
| | | function keys(object) { |
| | | if (Object.keys) { |
| | | return Object.keys(object); |
| | | } |
| | | var result = []; |
| | | |
| | | angular.forEach(object, function(val, key) { |
| | | result.push(key); |
| | | }); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * IE8-safe wrapper for `Array.prototype.indexOf()`. |
| | | * |
| | | * @param {Array} array A JavaScript array. |
| | | * @param {*} value A value to search the array for. |
| | | * @return {Number} Returns the array index value of `value`, or `-1` if not present. |
| | | */ |
| | | function arraySearch(array, value) { |
| | | if (Array.prototype.indexOf) { |
| | | return array.indexOf(value, Number(arguments[2]) || 0); |
| | | } |
| | | var len = array.length >>> 0, from = Number(arguments[2]) || 0; |
| | | from = (from < 0) ? Math.ceil(from) : Math.floor(from); |
| | | |
| | | if (from < 0) from += len; |
| | | |
| | | for (; from < len; from++) { |
| | | if (from in array && array[from] === value) return from; |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | /** |
| | | * Merges a set of parameters with all parameters inherited between the common parents of the |
| | | * current state and a given destination state. |
| | | * |
| | | * @param {Object} currentParams The value of the current state parameters ($stateParams). |
| | | * @param {Object} newParams The set of parameters which will be composited with inherited params. |
| | | * @param {Object} $current Internal definition of object representing the current state. |
| | | * @param {Object} $to Internal definition of object representing state to transition to. |
| | | */ |
| | | function inheritParams(currentParams, newParams, $current, $to) { |
| | | var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; |
| | | |
| | | for (var i in parents) { |
| | | if (!parents[i].params || !parents[i].params.length) continue; |
| | | parentParams = parents[i].params; |
| | | |
| | | for (var j in parentParams) { |
| | | if (arraySearch(inheritList, parentParams[j]) >= 0) continue; |
| | | inheritList.push(parentParams[j]); |
| | | inherited[parentParams[j]] = currentParams[parentParams[j]]; |
| | | } |
| | | } |
| | | return extend({}, inherited, newParams); |
| | | } |
| | | |
| | | /** |
| | | * Normalizes a set of values to string or `null`, filtering them by a list of keys. |
| | | * |
| | | * @param {Array} keys The list of keys to normalize/return. |
| | | * @param {Object} values An object hash of values to normalize. |
| | | * @return {Object} Returns an object hash of normalized string values. |
| | | */ |
| | | function normalize(keys, values) { |
| | | var normalized = {}; |
| | | |
| | | forEach(keys, function (name) { |
| | | var value = values[name]; |
| | | normalized[name] = (value != null) ? String(value) : null; |
| | | }); |
| | | return normalized; |
| | | } |
| | | |
| | | /** |
| | | * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. |
| | | * |
| | | * @param {Object} a The first object. |
| | | * @param {Object} b The second object. |
| | | * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, |
| | | * it defaults to the list of keys in `a`. |
| | | * @return {Boolean} Returns `true` if the keys match, otherwise `false`. |
| | | */ |
| | | function equalForKeys(a, b, keys) { |
| | | if (!keys) { |
| | | keys = []; |
| | | for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility |
| | | } |
| | | |
| | | for (var i=0; i<keys.length; i++) { |
| | | var k = keys[i]; |
| | | if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * Returns the subset of an object, based on a list of keys. |
| | | * |
| | | * @param {Array} keys |
| | | * @param {Object} values |
| | | * @return {Boolean} Returns a subset of `values`. |
| | | */ |
| | | function filterByKeys(keys, values) { |
| | | var filtered = {}; |
| | | |
| | | forEach(keys, function (name) { |
| | | filtered[name] = values[name]; |
| | | }); |
| | | return filtered; |
| | | } |
| | | /** |
| | | * @ngdoc overview |
| | | * @name ui.router.util |
| | | * |
| | | * @description |
| | | * # ui.router.util sub-module |
| | | * |
| | | * This module is a dependency of other sub-modules. Do not include this module as a dependency |
| | | * in your angular app (use {@link ui.router} module instead). |
| | | * |
| | | */ |
| | | angular.module('ui.router.util', ['ng']); |
| | | |
| | | /** |
| | | * @ngdoc overview |
| | | * @name ui.router.router |
| | | * |
| | | * @requires ui.router.util |
| | | * |
| | | * @description |
| | | * # ui.router.router sub-module |
| | | * |
| | | * This module is a dependency of other sub-modules. Do not include this module as a dependency |
| | | * in your angular app (use {@link ui.router} module instead). |
| | | */ |
| | | angular.module('ui.router.router', ['ui.router.util']); |
| | | |
| | | /** |
| | | * @ngdoc overview |
| | | * @name ui.router.state |
| | | * |
| | | * @requires ui.router.router |
| | | * @requires ui.router.util |
| | | * |
| | | * @description |
| | | * # ui.router.state sub-module |
| | | * |
| | | * This module is a dependency of the main ui.router module. Do not include this module as a dependency |
| | | * in your angular app (use {@link ui.router} module instead). |
| | | * |
| | | */ |
| | | angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']); |
| | | |
| | | /** |
| | | * @ngdoc overview |
| | | * @name ui.router |
| | | * |
| | | * @requires ui.router.state |
| | | * |
| | | * @description |
| | | * # ui.router |
| | | * |
| | | * ## The main module for ui.router |
| | | * There are several sub-modules included with the ui.router module, however only this module is needed |
| | | * as a dependency within your angular app. The other modules are for organization purposes. |
| | | * |
| | | * The modules are: |
| | | * * ui.router - the main "umbrella" module |
| | | * * ui.router.router - |
| | | * |
| | | * *You'll need to include **only** this module as the dependency within your angular app.* |
| | | * |
| | | * <pre> |
| | | * <!doctype html> |
| | | * <html ng-app="myApp"> |
| | | * <head> |
| | | * <script src="js/angular.js"></script> |
| | | * <!-- Include the ui-router script --> |
| | | * <script src="js/angular-ui-router.min.js"></script> |
| | | * <script> |
| | | * // ...and add 'ui.router' as a dependency |
| | | * var myApp = angular.module('myApp', ['ui.router']); |
| | | * </script> |
| | | * </head> |
| | | * <body> |
| | | * </body> |
| | | * </html> |
| | | * </pre> |
| | | */ |
| | | angular.module('ui.router', ['ui.router.state']); |
| | | |
| | | angular.module('ui.router.compat', ['ui.router']); |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.util.$resolve |
| | | * |
| | | * @requires $q |
| | | * @requires $injector |
| | | * |
| | | * @description |
| | | * Manages resolution of (acyclic) graphs of promises. |
| | | */ |
| | | $Resolve.$inject = ['$q', '$injector']; |
| | | function $Resolve( $q, $injector) { |
| | | |
| | | var VISIT_IN_PROGRESS = 1, |
| | | VISIT_DONE = 2, |
| | | NOTHING = {}, |
| | | NO_DEPENDENCIES = [], |
| | | NO_LOCALS = NOTHING, |
| | | NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING }); |
| | | |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$resolve#study |
| | | * @methodOf ui.router.util.$resolve |
| | | * |
| | | * @description |
| | | * Studies a set of invocables that are likely to be used multiple times. |
| | | * <pre> |
| | | * $resolve.study(invocables)(locals, parent, self) |
| | | * </pre> |
| | | * is equivalent to |
| | | * <pre> |
| | | * $resolve.resolve(invocables, locals, parent, self) |
| | | * </pre> |
| | | * but the former is more efficient (in fact `resolve` just calls `study` |
| | | * internally). |
| | | * |
| | | * @param {object} invocables Invocable objects |
| | | * @return {function} a function to pass in locals, parent and self |
| | | */ |
| | | this.study = function (invocables) { |
| | | if (!isObject(invocables)) throw new Error("'invocables' must be an object"); |
| | | |
| | | // Perform a topological sort of invocables to build an ordered plan |
| | | var plan = [], cycle = [], visited = {}; |
| | | function visit(value, key) { |
| | | if (visited[key] === VISIT_DONE) return; |
| | | |
| | | cycle.push(key); |
| | | if (visited[key] === VISIT_IN_PROGRESS) { |
| | | cycle.splice(0, cycle.indexOf(key)); |
| | | throw new Error("Cyclic dependency: " + cycle.join(" -> ")); |
| | | } |
| | | visited[key] = VISIT_IN_PROGRESS; |
| | | |
| | | if (isString(value)) { |
| | | plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES); |
| | | } else { |
| | | var params = $injector.annotate(value); |
| | | forEach(params, function (param) { |
| | | if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); |
| | | }); |
| | | plan.push(key, value, params); |
| | | } |
| | | |
| | | cycle.pop(); |
| | | visited[key] = VISIT_DONE; |
| | | } |
| | | forEach(invocables, visit); |
| | | invocables = cycle = visited = null; // plan is all that's required |
| | | |
| | | function isResolve(value) { |
| | | return isObject(value) && value.then && value.$$promises; |
| | | } |
| | | |
| | | return function (locals, parent, self) { |
| | | if (isResolve(locals) && self === undefined) { |
| | | self = parent; parent = locals; locals = null; |
| | | } |
| | | if (!locals) locals = NO_LOCALS; |
| | | else if (!isObject(locals)) { |
| | | throw new Error("'locals' must be an object"); |
| | | } |
| | | if (!parent) parent = NO_PARENT; |
| | | else if (!isResolve(parent)) { |
| | | throw new Error("'parent' must be a promise returned by $resolve.resolve()"); |
| | | } |
| | | |
| | | // To complete the overall resolution, we have to wait for the parent |
| | | // promise and for the promise for each invokable in our plan. |
| | | var resolution = $q.defer(), |
| | | result = resolution.promise, |
| | | promises = result.$$promises = {}, |
| | | values = extend({}, locals), |
| | | wait = 1 + plan.length/3, |
| | | merged = false; |
| | | |
| | | function done() { |
| | | // Merge parent values we haven't got yet and publish our own $$values |
| | | if (!--wait) { |
| | | if (!merged) merge(values, parent.$$values); |
| | | result.$$values = values; |
| | | result.$$promises = true; // keep for isResolve() |
| | | resolution.resolve(values); |
| | | } |
| | | } |
| | | |
| | | function fail(reason) { |
| | | result.$$failure = reason; |
| | | resolution.reject(reason); |
| | | } |
| | | |
| | | // Short-circuit if parent has already failed |
| | | if (isDefined(parent.$$failure)) { |
| | | fail(parent.$$failure); |
| | | return result; |
| | | } |
| | | |
| | | // Merge parent values if the parent has already resolved, or merge |
| | | // parent promises and wait if the parent resolve is still in progress. |
| | | if (parent.$$values) { |
| | | merged = merge(values, parent.$$values); |
| | | done(); |
| | | } else { |
| | | extend(promises, parent.$$promises); |
| | | parent.then(done, fail); |
| | | } |
| | | |
| | | // Process each invocable in the plan, but ignore any where a local of the same name exists. |
| | | for (var i=0, ii=plan.length; i<ii; i+=3) { |
| | | if (locals.hasOwnProperty(plan[i])) done(); |
| | | else invoke(plan[i], plan[i+1], plan[i+2]); |
| | | } |
| | | |
| | | function invoke(key, invocable, params) { |
| | | // Create a deferred for this invocation. Failures will propagate to the resolution as well. |
| | | var invocation = $q.defer(), waitParams = 0; |
| | | function onfailure(reason) { |
| | | invocation.reject(reason); |
| | | fail(reason); |
| | | } |
| | | // Wait for any parameter that we have a promise for (either from parent or from this |
| | | // resolve; in that case study() will have made sure it's ordered before us in the plan). |
| | | forEach(params, function (dep) { |
| | | if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) { |
| | | waitParams++; |
| | | promises[dep].then(function (result) { |
| | | values[dep] = result; |
| | | if (!(--waitParams)) proceed(); |
| | | }, onfailure); |
| | | } |
| | | }); |
| | | if (!waitParams) proceed(); |
| | | function proceed() { |
| | | if (isDefined(result.$$failure)) return; |
| | | try { |
| | | invocation.resolve($injector.invoke(invocable, self, values)); |
| | | invocation.promise.then(function (result) { |
| | | values[key] = result; |
| | | done(); |
| | | }, onfailure); |
| | | } catch (e) { |
| | | onfailure(e); |
| | | } |
| | | } |
| | | // Publish promise synchronously; invocations further down in the plan may depend on it. |
| | | promises[key] = invocation.promise; |
| | | } |
| | | |
| | | return result; |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$resolve#resolve |
| | | * @methodOf ui.router.util.$resolve |
| | | * |
| | | * @description |
| | | * Resolves a set of invocables. An invocable is a function to be invoked via |
| | | * `$injector.invoke()`, and can have an arbitrary number of dependencies. |
| | | * An invocable can either return a value directly, |
| | | * or a `$q` promise. If a promise is returned it will be resolved and the |
| | | * resulting value will be used instead. Dependencies of invocables are resolved |
| | | * (in this order of precedence) |
| | | * |
| | | * - from the specified `locals` |
| | | * - from another invocable that is part of this `$resolve` call |
| | | * - from an invocable that is inherited from a `parent` call to `$resolve` |
| | | * (or recursively |
| | | * - from any ancestor `$resolve` of that parent). |
| | | * |
| | | * The return value of `$resolve` is a promise for an object that contains |
| | | * (in this order of precedence) |
| | | * |
| | | * - any `locals` (if specified) |
| | | * - the resolved return values of all injectables |
| | | * - any values inherited from a `parent` call to `$resolve` (if specified) |
| | | * |
| | | * The promise will resolve after the `parent` promise (if any) and all promises |
| | | * returned by injectables have been resolved. If any invocable |
| | | * (or `$injector.invoke`) throws an exception, or if a promise returned by an |
| | | * invocable is rejected, the `$resolve` promise is immediately rejected with the |
| | | * same error. A rejection of a `parent` promise (if specified) will likewise be |
| | | * propagated immediately. Once the `$resolve` promise has been rejected, no |
| | | * further invocables will be called. |
| | | * |
| | | * Cyclic dependencies between invocables are not permitted and will caues `$resolve` |
| | | * to throw an error. As a special case, an injectable can depend on a parameter |
| | | * with the same name as the injectable, which will be fulfilled from the `parent` |
| | | * injectable of the same name. This allows inherited values to be decorated. |
| | | * Note that in this case any other injectable in the same `$resolve` with the same |
| | | * dependency would see the decorated value, not the inherited value. |
| | | * |
| | | * Note that missing dependencies -- unlike cyclic dependencies -- will cause an |
| | | * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous) |
| | | * exception. |
| | | * |
| | | * Invocables are invoked eagerly as soon as all dependencies are available. |
| | | * This is true even for dependencies inherited from a `parent` call to `$resolve`. |
| | | * |
| | | * As a special case, an invocable can be a string, in which case it is taken to |
| | | * be a service name to be passed to `$injector.get()`. This is supported primarily |
| | | * for backwards-compatibility with the `resolve` property of `$routeProvider` |
| | | * routes. |
| | | * |
| | | * @param {object} invocables functions to invoke or |
| | | * `$injector` services to fetch. |
| | | * @param {object} locals values to make available to the injectables |
| | | * @param {object} parent a promise returned by another call to `$resolve`. |
| | | * @param {object} self the `this` for the invoked methods |
| | | * @return {object} Promise for an object that contains the resolved return value |
| | | * of all invocables, as well as any inherited and local values. |
| | | */ |
| | | this.resolve = function (invocables, locals, parent, self) { |
| | | return this.study(invocables)(locals, parent, self); |
| | | }; |
| | | } |
| | | |
| | | angular.module('ui.router.util').service('$resolve', $Resolve); |
| | | |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.util.$templateFactory |
| | | * |
| | | * @requires $http |
| | | * @requires $templateCache |
| | | * @requires $injector |
| | | * |
| | | * @description |
| | | * Service. Manages loading of templates. |
| | | */ |
| | | $TemplateFactory.$inject = ['$http', '$templateCache', '$injector']; |
| | | function $TemplateFactory( $http, $templateCache, $injector) { |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$templateFactory#fromConfig |
| | | * @methodOf ui.router.util.$templateFactory |
| | | * |
| | | * @description |
| | | * Creates a template from a configuration object. |
| | | * |
| | | * @param {object} config Configuration object for which to load a template. |
| | | * The following properties are search in the specified order, and the first one |
| | | * that is defined is used to create the template: |
| | | * |
| | | * @param {string|object} config.template html string template or function to |
| | | * load via {@link ui.router.util.$templateFactory#fromString fromString}. |
| | | * @param {string|object} config.templateUrl url to load or a function returning |
| | | * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}. |
| | | * @param {Function} config.templateProvider function to invoke via |
| | | * {@link ui.router.util.$templateFactory#fromProvider fromProvider}. |
| | | * @param {object} params Parameters to pass to the template function. |
| | | * @param {object} locals Locals to pass to `invoke` if the template is loaded |
| | | * via a `templateProvider`. Defaults to `{ params: params }`. |
| | | * |
| | | * @return {string|object} The template html as a string, or a promise for |
| | | * that string,or `null` if no template is configured. |
| | | */ |
| | | this.fromConfig = function (config, params, locals) { |
| | | return ( |
| | | isDefined(config.template) ? this.fromString(config.template, params) : |
| | | isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) : |
| | | isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) : |
| | | null |
| | | ); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$templateFactory#fromString |
| | | * @methodOf ui.router.util.$templateFactory |
| | | * |
| | | * @description |
| | | * Creates a template from a string or a function returning a string. |
| | | * |
| | | * @param {string|object} template html template as a string or function that |
| | | * returns an html template as a string. |
| | | * @param {object} params Parameters to pass to the template function. |
| | | * |
| | | * @return {string|object} The template html as a string, or a promise for that |
| | | * string. |
| | | */ |
| | | this.fromString = function (template, params) { |
| | | return isFunction(template) ? template(params) : template; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$templateFactory#fromUrl |
| | | * @methodOf ui.router.util.$templateFactory |
| | | * |
| | | * @description |
| | | * Loads a template from the a URL via `$http` and `$templateCache`. |
| | | * |
| | | * @param {string|Function} url url of the template to load, or a function |
| | | * that returns a url. |
| | | * @param {Object} params Parameters to pass to the url function. |
| | | * @return {string|Promise.<string>} The template html as a string, or a promise |
| | | * for that string. |
| | | */ |
| | | this.fromUrl = function (url, params) { |
| | | if (isFunction(url)) url = url(params); |
| | | if (url == null) return null; |
| | | else return $http |
| | | .get(url, { cache: $templateCache }) |
| | | .then(function(response) { return response.data; }); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$templateFactory#fromUrl |
| | | * @methodOf ui.router.util.$templateFactory |
| | | * |
| | | * @description |
| | | * Creates a template by invoking an injectable provider function. |
| | | * |
| | | * @param {Function} provider Function to invoke via `$injector.invoke` |
| | | * @param {Object} params Parameters for the template. |
| | | * @param {Object} locals Locals to pass to `invoke`. Defaults to |
| | | * `{ params: params }`. |
| | | * @return {string|Promise.<string>} The template html as a string, or a promise |
| | | * for that string. |
| | | */ |
| | | this.fromProvider = function (provider, params, locals) { |
| | | return $injector.invoke(provider, null, locals || { params: params }); |
| | | }; |
| | | } |
| | | |
| | | angular.module('ui.router.util').service('$templateFactory', $TemplateFactory); |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.util.type:UrlMatcher |
| | | * |
| | | * @description |
| | | * Matches URLs against patterns and extracts named parameters from the path or the search |
| | | * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list |
| | | * of search parameters. Multiple search parameter names are separated by '&'. Search parameters |
| | | * do not influence whether or not a URL is matched, but their values are passed through into |
| | | * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}. |
| | | * |
| | | * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace |
| | | * syntax, which optionally allows a regular expression for the parameter to be specified: |
| | | * |
| | | * * `':'` name - colon placeholder |
| | | * * `'*'` name - catch-all placeholder |
| | | * * `'{' name '}'` - curly placeholder |
| | | * * `'{' name ':' regexp '}'` - curly placeholder with regexp. Should the regexp itself contain |
| | | * curly braces, they must be in matched pairs or escaped with a backslash. |
| | | * |
| | | * Parameter names may contain only word characters (latin letters, digits, and underscore) and |
| | | * must be unique within the pattern (across both path and search parameters). For colon |
| | | * placeholders or curly placeholders without an explicit regexp, a path parameter matches any |
| | | * number of characters other than '/'. For catch-all placeholders the path parameter matches |
| | | * any number of characters. |
| | | * |
| | | * Examples: |
| | | * |
| | | * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for |
| | | * trailing slashes, and patterns have to match the entire path, not just a prefix. |
| | | * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or |
| | | * '/user/bob/details'. The second path segment will be captured as the parameter 'id'. |
| | | * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax. |
| | | * * `'/user/{id:[^/]*}'` - Same as the previous example. |
| | | * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id |
| | | * parameter consists of 1 to 8 hex digits. |
| | | * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the |
| | | * path into the parameter 'path'. |
| | | * * `'/files/*path'` - ditto. |
| | | * |
| | | * @param {string} pattern the pattern to compile into a matcher. |
| | | * |
| | | * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any |
| | | * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns |
| | | * non-null) will start with this prefix. |
| | | * |
| | | * @property {string} source The pattern that was passed into the contructor |
| | | * |
| | | * @property {string} sourcePath The path portion of the source property |
| | | * |
| | | * @property {string} sourceSearch The search portion of the source property |
| | | * |
| | | * @property {string} regex The constructed regex that will be used to match against the url when |
| | | * it is time to determine which url will match. |
| | | * |
| | | * @returns {Object} New UrlMatcher object |
| | | */ |
| | | function UrlMatcher(pattern) { |
| | | |
| | | // Find all placeholders and create a compiled pattern, using either classic or curly syntax: |
| | | // '*' name |
| | | // ':' name |
| | | // '{' name '}' |
| | | // '{' name ':' regexp '}' |
| | | // The regular expression is somewhat complicated due to the need to allow curly braces |
| | | // inside the regular expression. The placeholder regexp breaks down as follows: |
| | | // ([:*])(\w+) classic placeholder ($1 / $2) |
| | | // \{(\w+)(?:\:( ... ))?\} curly brace placeholder ($3) with optional regexp ... ($4) |
| | | // (?: ... | ... | ... )+ the regexp consists of any number of atoms, an atom being either |
| | | // [^{}\\]+ - anything other than curly braces or backslash |
| | | // \\. - a backslash escape |
| | | // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms |
| | | var placeholder = /([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, |
| | | names = {}, compiled = '^', last = 0, m, |
| | | segments = this.segments = [], |
| | | params = this.params = []; |
| | | |
| | | function addParameter(id) { |
| | | if (!/^\w+(-+\w+)*$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); |
| | | if (names[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); |
| | | names[id] = true; |
| | | params.push(id); |
| | | } |
| | | |
| | | function quoteRegExp(string) { |
| | | return string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); |
| | | } |
| | | |
| | | this.source = pattern; |
| | | |
| | | // Split into static segments separated by path parameter placeholders. |
| | | // The number of segments is always 1 more than the number of parameters. |
| | | var id, regexp, segment; |
| | | while ((m = placeholder.exec(pattern))) { |
| | | id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null |
| | | regexp = m[4] || (m[1] == '*' ? '.*' : '[^/]*'); |
| | | segment = pattern.substring(last, m.index); |
| | | if (segment.indexOf('?') >= 0) break; // we're into the search part |
| | | compiled += quoteRegExp(segment) + '(' + regexp + ')'; |
| | | addParameter(id); |
| | | segments.push(segment); |
| | | last = placeholder.lastIndex; |
| | | } |
| | | segment = pattern.substring(last); |
| | | |
| | | // Find any search parameter names and remove them from the last segment |
| | | var i = segment.indexOf('?'); |
| | | if (i >= 0) { |
| | | var search = this.sourceSearch = segment.substring(i); |
| | | segment = segment.substring(0, i); |
| | | this.sourcePath = pattern.substring(0, last+i); |
| | | |
| | | // Allow parameters to be separated by '?' as well as '&' to make concat() easier |
| | | forEach(search.substring(1).split(/[&?]/), addParameter); |
| | | } else { |
| | | this.sourcePath = pattern; |
| | | this.sourceSearch = ''; |
| | | } |
| | | |
| | | compiled += quoteRegExp(segment) + '$'; |
| | | segments.push(segment); |
| | | this.regexp = new RegExp(compiled); |
| | | this.prefix = segments[0]; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.type:UrlMatcher#concat |
| | | * @methodOf ui.router.util.type:UrlMatcher |
| | | * |
| | | * @description |
| | | * Returns a new matcher for a pattern constructed by appending the path part and adding the |
| | | * search parameters of the specified pattern to this pattern. The current pattern is not |
| | | * modified. This can be understood as creating a pattern for URLs that are relative to (or |
| | | * suffixes of) the current pattern. |
| | | * |
| | | * @example |
| | | * The following two matchers are equivalent: |
| | | * ``` |
| | | * new UrlMatcher('/user/{id}?q').concat('/details?date'); |
| | | * new UrlMatcher('/user/{id}/details?q&date'); |
| | | * ``` |
| | | * |
| | | * @param {string} pattern The pattern to append. |
| | | * @returns {ui.router.util.type:UrlMatcher} A matcher for the concatenated pattern. |
| | | */ |
| | | UrlMatcher.prototype.concat = function (pattern) { |
| | | // Because order of search parameters is irrelevant, we can add our own search |
| | | // parameters to the end of the new pattern. Parse the new pattern by itself |
| | | // and then join the bits together, but it's much easier to do this on a string level. |
| | | return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch); |
| | | }; |
| | | |
| | | UrlMatcher.prototype.toString = function () { |
| | | return this.source; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.type:UrlMatcher#exec |
| | | * @methodOf ui.router.util.type:UrlMatcher |
| | | * |
| | | * @description |
| | | * Tests the specified path against this matcher, and returns an object containing the captured |
| | | * parameter values, or null if the path does not match. The returned object contains the values |
| | | * of any search parameters that are mentioned in the pattern, but their value may be null if |
| | | * they are not present in `searchParams`. This means that search parameters are always treated |
| | | * as optional. |
| | | * |
| | | * @example |
| | | * ``` |
| | | * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', { x:'1', q:'hello' }); |
| | | * // returns { id:'bob', q:'hello', r:null } |
| | | * ``` |
| | | * |
| | | * @param {string} path The URL path to match, e.g. `$location.path()`. |
| | | * @param {Object} searchParams URL search parameters, e.g. `$location.search()`. |
| | | * @returns {Object} The captured parameter values. |
| | | */ |
| | | UrlMatcher.prototype.exec = function (path, searchParams) { |
| | | var m = this.regexp.exec(path); |
| | | if (!m) return null; |
| | | |
| | | var params = this.params, nTotal = params.length, |
| | | nPath = this.segments.length-1, |
| | | values = {}, i; |
| | | |
| | | if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); |
| | | |
| | | for (i=0; i<nPath; i++) values[params[i]] = m[i+1]; |
| | | for (/**/; i<nTotal; i++) values[params[i]] = searchParams[params[i]]; |
| | | |
| | | return values; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.type:UrlMatcher#parameters |
| | | * @methodOf ui.router.util.type:UrlMatcher |
| | | * |
| | | * @description |
| | | * Returns the names of all path and search parameters of this pattern in an unspecified order. |
| | | * |
| | | * @returns {Array.<string>} An array of parameter names. Must be treated as read-only. If the |
| | | * pattern has no parameters, an empty array is returned. |
| | | */ |
| | | UrlMatcher.prototype.parameters = function () { |
| | | return this.params; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.type:UrlMatcher#format |
| | | * @methodOf ui.router.util.type:UrlMatcher |
| | | * |
| | | * @description |
| | | * Creates a URL that matches this pattern by substituting the specified values |
| | | * for the path and search parameters. Null values for path parameters are |
| | | * treated as empty strings. |
| | | * |
| | | * @example |
| | | * ``` |
| | | * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' }); |
| | | * // returns '/user/bob?q=yes' |
| | | * ``` |
| | | * |
| | | * @param {Object} values the values to substitute for the parameters in this pattern. |
| | | * @returns {string} the formatted URL (path and optionally search part). |
| | | */ |
| | | UrlMatcher.prototype.format = function (values) { |
| | | var segments = this.segments, params = this.params; |
| | | if (!values) return segments.join(''); |
| | | |
| | | var nPath = segments.length-1, nTotal = params.length, |
| | | result = segments[0], i, search, value; |
| | | |
| | | for (i=0; i<nPath; i++) { |
| | | value = values[params[i]]; |
| | | // TODO: Maybe we should throw on null here? It's not really good style to use '' and null interchangeabley |
| | | if (value != null) result += encodeURIComponent(value); |
| | | result += segments[i+1]; |
| | | } |
| | | for (/**/; i<nTotal; i++) { |
| | | value = values[params[i]]; |
| | | if (value != null) { |
| | | result += (search ? '&' : '?') + params[i] + '=' + encodeURIComponent(value); |
| | | search = true; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | }; |
| | | |
| | | |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.util.$urlMatcherFactory |
| | | * |
| | | * @description |
| | | * Factory for {@link ui.router.util.type:UrlMatcher} instances. The factory is also available to providers |
| | | * under the name `$urlMatcherFactoryProvider`. |
| | | */ |
| | | function $UrlMatcherFactory() { |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$urlMatcherFactory#compile |
| | | * @methodOf ui.router.util.$urlMatcherFactory |
| | | * |
| | | * @description |
| | | * Creates a {@link ui.router.util.type:UrlMatcher} for the specified pattern. |
| | | * |
| | | * @param {string} pattern The URL pattern. |
| | | * @returns {ui.router.util.type:UrlMatcher} The UrlMatcher. |
| | | */ |
| | | this.compile = function (pattern) { |
| | | return new UrlMatcher(pattern); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.util.$urlMatcherFactory#isMatcher |
| | | * @methodOf ui.router.util.$urlMatcherFactory |
| | | * |
| | | * @description |
| | | * Returns true if the specified object is a UrlMatcher, or false otherwise. |
| | | * |
| | | * @param {Object} object The object to perform the type check against. |
| | | * @returns {Boolean} Returns `true` if the object has the following functions: `exec`, `format`, and `concat`. |
| | | */ |
| | | this.isMatcher = function (o) { |
| | | return isObject(o) && isFunction(o.exec) && isFunction(o.format) && isFunction(o.concat); |
| | | }; |
| | | |
| | | /* No need to document $get, since it returns this */ |
| | | this.$get = function () { |
| | | return this; |
| | | }; |
| | | } |
| | | |
| | | // Register as a provider so it's available to other providers |
| | | angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory); |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.router.$urlRouterProvider |
| | | * |
| | | * @requires ui.router.util.$urlMatcherFactoryProvider |
| | | * |
| | | * @description |
| | | * `$urlRouterProvider` has the responsibility of watching `$location`. |
| | | * When `$location` changes it runs through a list of rules one by one until a |
| | | * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify |
| | | * a url in a state configuration. All urls are compiled into a UrlMatcher object. |
| | | * |
| | | * There are several methods on `$urlRouterProvider` that make it useful to use directly |
| | | * in your module config. |
| | | */ |
| | | $UrlRouterProvider.$inject = ['$urlMatcherFactoryProvider']; |
| | | function $UrlRouterProvider( $urlMatcherFactory) { |
| | | var rules = [], |
| | | otherwise = null; |
| | | |
| | | // Returns a string that is a prefix of all strings matching the RegExp |
| | | function regExpPrefix(re) { |
| | | var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); |
| | | return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; |
| | | } |
| | | |
| | | // Interpolates matched values into a String.replace()-style pattern |
| | | function interpolate(pattern, match) { |
| | | return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { |
| | | return match[what === '$' ? 0 : Number(what)]; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.router.$urlRouterProvider#rule |
| | | * @methodOf ui.router.router.$urlRouterProvider |
| | | * |
| | | * @description |
| | | * Defines rules that are used by `$urlRouterProvider to find matches for |
| | | * specific URLs. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router.router']); |
| | | * |
| | | * app.config(function ($urlRouterProvider) { |
| | | * // Here's an example of how you might allow case insensitive urls |
| | | * $urlRouterProvider.rule(function ($injector, $location) { |
| | | * var path = $location.path(), |
| | | * normalized = path.toLowerCase(); |
| | | * |
| | | * if (path !== normalized) { |
| | | * return normalized; |
| | | * } |
| | | * }); |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * @param {object} rule Handler function that takes `$injector` and `$location` |
| | | * services as arguments. You can use them to return a valid path as a string. |
| | | * |
| | | * @return {object} $urlRouterProvider - $urlRouterProvider instance |
| | | */ |
| | | this.rule = |
| | | function (rule) { |
| | | if (!isFunction(rule)) throw new Error("'rule' must be a function"); |
| | | rules.push(rule); |
| | | return this; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.router.$urlRouterProvider#otherwise |
| | | * @methodOf ui.router.router.$urlRouterProvider |
| | | * |
| | | * @description |
| | | * Defines a path that is used when an invalied route is requested. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router.router']); |
| | | * |
| | | * app.config(function ($urlRouterProvider) { |
| | | * // if the path doesn't match any of the urls you configured |
| | | * // otherwise will take care of routing the user to the |
| | | * // specified url |
| | | * $urlRouterProvider.otherwise('/index'); |
| | | * |
| | | * // Example of using function rule as param |
| | | * $urlRouterProvider.otherwise(function ($injector, $location) { |
| | | * ... |
| | | * }); |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * @param {string|object} rule The url path you want to redirect to or a function |
| | | * rule that returns the url path. The function version is passed two params: |
| | | * `$injector` and `$location` services. |
| | | * |
| | | * @return {object} $urlRouterProvider - $urlRouterProvider instance |
| | | */ |
| | | this.otherwise = |
| | | function (rule) { |
| | | if (isString(rule)) { |
| | | var redirect = rule; |
| | | rule = function () { return redirect; }; |
| | | } |
| | | else if (!isFunction(rule)) throw new Error("'rule' must be a function"); |
| | | otherwise = rule; |
| | | return this; |
| | | }; |
| | | |
| | | |
| | | function handleIfMatch($injector, handler, match) { |
| | | if (!match) return false; |
| | | var result = $injector.invoke(handler, handler, { $match: match }); |
| | | return isDefined(result) ? result : true; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.router.$urlRouterProvider#when |
| | | * @methodOf ui.router.router.$urlRouterProvider |
| | | * |
| | | * @description |
| | | * Registers a handler for a given url matching. if handle is a string, it is |
| | | * treated as a redirect, and is interpolated according to the syyntax of match |
| | | * (i.e. like String.replace() for RegExp, or like a UrlMatcher pattern otherwise). |
| | | * |
| | | * If the handler is a function, it is injectable. It gets invoked if `$location` |
| | | * matches. You have the option of inject the match object as `$match`. |
| | | * |
| | | * The handler can return |
| | | * |
| | | * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` |
| | | * will continue trying to find another one that matches. |
| | | * - **string** which is treated as a redirect and passed to `$location.url()` |
| | | * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router.router']); |
| | | * |
| | | * app.config(function ($urlRouterProvider) { |
| | | * $urlRouterProvider.when($state.url, function ($match, $stateParams) { |
| | | * if ($state.$current.navigable !== state || |
| | | * !equalForKeys($match, $stateParams) { |
| | | * $state.transitionTo(state, $match, false); |
| | | * } |
| | | * }); |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * @param {string|object} what The incoming path that you want to redirect. |
| | | * @param {string|object} handler The path you want to redirect your user to. |
| | | */ |
| | | this.when = |
| | | function (what, handler) { |
| | | var redirect, handlerIsString = isString(handler); |
| | | if (isString(what)) what = $urlMatcherFactory.compile(what); |
| | | |
| | | if (!handlerIsString && !isFunction(handler) && !isArray(handler)) |
| | | throw new Error("invalid 'handler' in when()"); |
| | | |
| | | var strategies = { |
| | | matcher: function (what, handler) { |
| | | if (handlerIsString) { |
| | | redirect = $urlMatcherFactory.compile(handler); |
| | | handler = ['$match', function ($match) { return redirect.format($match); }]; |
| | | } |
| | | return extend(function ($injector, $location) { |
| | | return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); |
| | | }, { |
| | | prefix: isString(what.prefix) ? what.prefix : '' |
| | | }); |
| | | }, |
| | | regex: function (what, handler) { |
| | | if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); |
| | | |
| | | if (handlerIsString) { |
| | | redirect = handler; |
| | | handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; |
| | | } |
| | | return extend(function ($injector, $location) { |
| | | return handleIfMatch($injector, handler, what.exec($location.path())); |
| | | }, { |
| | | prefix: regExpPrefix(what) |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp }; |
| | | |
| | | for (var n in check) { |
| | | if (check[n]) { |
| | | return this.rule(strategies[n](what, handler)); |
| | | } |
| | | } |
| | | |
| | | throw new Error("invalid 'what' in when()"); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.router.$urlRouter |
| | | * |
| | | * @requires $location |
| | | * @requires $rootScope |
| | | * @requires $injector |
| | | * |
| | | * @description |
| | | * |
| | | */ |
| | | this.$get = |
| | | [ '$location', '$rootScope', '$injector', |
| | | function ($location, $rootScope, $injector) { |
| | | // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree |
| | | function update(evt) { |
| | | if (evt && evt.defaultPrevented) return; |
| | | function check(rule) { |
| | | var handled = rule($injector, $location); |
| | | if (handled) { |
| | | if (isString(handled)) $location.replace().url(handled); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | var n=rules.length, i; |
| | | for (i=0; i<n; i++) { |
| | | if (check(rules[i])) return; |
| | | } |
| | | // always check otherwise last to allow dynamic updates to the set of rules |
| | | if (otherwise) check(otherwise); |
| | | } |
| | | |
| | | $rootScope.$on('$locationChangeSuccess', update); |
| | | |
| | | return { |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.router.$urlRouter#sync |
| | | * @methodOf ui.router.router.$urlRouter |
| | | * |
| | | * @description |
| | | * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. |
| | | * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, |
| | | * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed |
| | | * with the transition by calling `$urlRouter.sync()`. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * angular.module('app', ['ui.router']); |
| | | * .run(function($rootScope, $urlRouter) { |
| | | * $rootScope.$on('$locationChangeSuccess', function(evt) { |
| | | * // Halt state change from even starting |
| | | * evt.preventDefault(); |
| | | * // Perform custom logic |
| | | * var meetsRequirement = ... |
| | | * // Continue with the update and state transition if logic allows |
| | | * if (meetsRequirement) $urlRouter.sync(); |
| | | * }); |
| | | * }); |
| | | * </pre> |
| | | */ |
| | | sync: function () { |
| | | update(); |
| | | } |
| | | }; |
| | | }]; |
| | | } |
| | | |
| | | angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider); |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.state.$stateProvider |
| | | * |
| | | * @requires ui.router.router.$urlRouterProvider |
| | | * @requires ui.router.util.$urlMatcherFactoryProvider |
| | | * @requires $locationProvider |
| | | * |
| | | * @description |
| | | * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely |
| | | * on state. |
| | | * |
| | | * A state corresponds to a "place" in the application in terms of the overall UI and |
| | | * navigation. A state describes (via the controller / template / view properties) what |
| | | * the UI looks like and does at that place. |
| | | * |
| | | * States often have things in common, and the primary way of factoring out these |
| | | * commonalities in this model is via the state hierarchy, i.e. parent/child states aka |
| | | * nested states. |
| | | * |
| | | * The `$stateProvider` provides interfaces to declare these states for your app. |
| | | */ |
| | | $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider']; |
| | | function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) { |
| | | |
| | | var root, states = {}, $state, queue = {}, abstractKey = 'abstract'; |
| | | |
| | | // Builds state properties from definition passed to registerState() |
| | | var stateBuilder = { |
| | | |
| | | // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined. |
| | | // state.children = []; |
| | | // if (parent) parent.children.push(state); |
| | | parent: function(state) { |
| | | if (isDefined(state.parent) && state.parent) return findState(state.parent); |
| | | // regex matches any valid composite state name |
| | | // would match "contact.list" but not "contacts" |
| | | var compositeName = /^(.+)\.[^.]+$/.exec(state.name); |
| | | return compositeName ? findState(compositeName[1]) : root; |
| | | }, |
| | | |
| | | // inherit 'data' from parent and override by own values (if any) |
| | | data: function(state) { |
| | | if (state.parent && state.parent.data) { |
| | | state.data = state.self.data = extend({}, state.parent.data, state.data); |
| | | } |
| | | return state.data; |
| | | }, |
| | | |
| | | // Build a URLMatcher if necessary, either via a relative or absolute URL |
| | | url: function(state) { |
| | | var url = state.url; |
| | | |
| | | if (isString(url)) { |
| | | if (url.charAt(0) == '^') { |
| | | return $urlMatcherFactory.compile(url.substring(1)); |
| | | } |
| | | return (state.parent.navigable || root).url.concat(url); |
| | | } |
| | | |
| | | if ($urlMatcherFactory.isMatcher(url) || url == null) { |
| | | return url; |
| | | } |
| | | throw new Error("Invalid url '" + url + "' in state '" + state + "'"); |
| | | }, |
| | | |
| | | // Keep track of the closest ancestor state that has a URL (i.e. is navigable) |
| | | navigable: function(state) { |
| | | return state.url ? state : (state.parent ? state.parent.navigable : null); |
| | | }, |
| | | |
| | | // Derive parameters for this state and ensure they're a super-set of parent's parameters |
| | | params: function(state) { |
| | | if (!state.params) { |
| | | return state.url ? state.url.parameters() : state.parent.params; |
| | | } |
| | | if (!isArray(state.params)) throw new Error("Invalid params in state '" + state + "'"); |
| | | if (state.url) throw new Error("Both params and url specicified in state '" + state + "'"); |
| | | return state.params; |
| | | }, |
| | | |
| | | // If there is no explicit multi-view configuration, make one up so we don't have |
| | | // to handle both cases in the view directive later. Note that having an explicit |
| | | // 'views' property will mean the default unnamed view properties are ignored. This |
| | | // is also a good time to resolve view names to absolute names, so everything is a |
| | | // straight lookup at link time. |
| | | views: function(state) { |
| | | var views = {}; |
| | | |
| | | forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) { |
| | | if (name.indexOf('@') < 0) name += '@' + state.parent.name; |
| | | views[name] = view; |
| | | }); |
| | | return views; |
| | | }, |
| | | |
| | | ownParams: function(state) { |
| | | if (!state.parent) { |
| | | return state.params; |
| | | } |
| | | var paramNames = {}; forEach(state.params, function (p) { paramNames[p] = true; }); |
| | | |
| | | forEach(state.parent.params, function (p) { |
| | | if (!paramNames[p]) { |
| | | throw new Error("Missing required parameter '" + p + "' in state '" + state.name + "'"); |
| | | } |
| | | paramNames[p] = false; |
| | | }); |
| | | var ownParams = []; |
| | | |
| | | forEach(paramNames, function (own, p) { |
| | | if (own) ownParams.push(p); |
| | | }); |
| | | return ownParams; |
| | | }, |
| | | |
| | | // Keep a full path from the root down to this state as this is needed for state activation. |
| | | path: function(state) { |
| | | return state.parent ? state.parent.path.concat(state) : []; // exclude root from path |
| | | }, |
| | | |
| | | // Speed up $state.contains() as it's used a lot |
| | | includes: function(state) { |
| | | var includes = state.parent ? extend({}, state.parent.includes) : {}; |
| | | includes[state.name] = true; |
| | | return includes; |
| | | }, |
| | | |
| | | $delegates: {} |
| | | }; |
| | | |
| | | function isRelative(stateName) { |
| | | return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; |
| | | } |
| | | |
| | | function findState(stateOrName, base) { |
| | | var isStr = isString(stateOrName), |
| | | name = isStr ? stateOrName : stateOrName.name, |
| | | path = isRelative(name); |
| | | |
| | | if (path) { |
| | | if (!base) throw new Error("No reference point given for path '" + name + "'"); |
| | | var rel = name.split("."), i = 0, pathLength = rel.length, current = base; |
| | | |
| | | for (; i < pathLength; i++) { |
| | | if (rel[i] === "" && i === 0) { |
| | | current = base; |
| | | continue; |
| | | } |
| | | if (rel[i] === "^") { |
| | | if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'"); |
| | | current = current.parent; |
| | | continue; |
| | | } |
| | | break; |
| | | } |
| | | rel = rel.slice(i).join("."); |
| | | name = current.name + (current.name && rel ? "." : "") + rel; |
| | | } |
| | | var state = states[name]; |
| | | |
| | | if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) { |
| | | return state; |
| | | } |
| | | return undefined; |
| | | } |
| | | |
| | | function queueState(parentName, state) { |
| | | if (!queue[parentName]) { |
| | | queue[parentName] = []; |
| | | } |
| | | queue[parentName].push(state); |
| | | } |
| | | |
| | | function registerState(state) { |
| | | // Wrap a new object around the state so we can store our private details easily. |
| | | state = inherit(state, { |
| | | self: state, |
| | | resolve: state.resolve || {}, |
| | | toString: function() { return this.name; } |
| | | }); |
| | | |
| | | var name = state.name; |
| | | if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name"); |
| | | if (states.hasOwnProperty(name)) throw new Error("State '" + name + "'' is already defined"); |
| | | |
| | | // Get parent name |
| | | var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.')) |
| | | : (isString(state.parent)) ? state.parent |
| | | : ''; |
| | | |
| | | // If parent is not registered yet, add state to queue and register later |
| | | if (parentName && !states[parentName]) { |
| | | return queueState(parentName, state.self); |
| | | } |
| | | |
| | | for (var key in stateBuilder) { |
| | | if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); |
| | | } |
| | | states[name] = state; |
| | | |
| | | // Register the state in the global state list and with $urlRouter if necessary. |
| | | if (!state[abstractKey] && state.url) { |
| | | $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { |
| | | if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { |
| | | $state.transitionTo(state, $match, { location: false }); |
| | | } |
| | | }]); |
| | | } |
| | | |
| | | // Register any queued children |
| | | if (queue[name]) { |
| | | for (var i = 0; i < queue[name].length; i++) { |
| | | registerState(queue[name][i]); |
| | | } |
| | | } |
| | | |
| | | return state; |
| | | } |
| | | |
| | | // Checks text to see if it looks like a glob. |
| | | function isGlob (text) { |
| | | return text.indexOf('*') > -1; |
| | | } |
| | | |
| | | // Returns true if glob matches current $state name. |
| | | function doesStateMatchGlob (glob) { |
| | | var globSegments = glob.split('.'), |
| | | segments = $state.$current.name.split('.'); |
| | | |
| | | //match greedy starts |
| | | if (globSegments[0] === '**') { |
| | | segments = segments.slice(segments.indexOf(globSegments[1])); |
| | | segments.unshift('**'); |
| | | } |
| | | //match greedy ends |
| | | if (globSegments[globSegments.length - 1] === '**') { |
| | | segments.splice(segments.indexOf(globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); |
| | | segments.push('**'); |
| | | } |
| | | |
| | | if (globSegments.length != segments.length) { |
| | | return false; |
| | | } |
| | | |
| | | //match single stars |
| | | for (var i = 0, l = globSegments.length; i < l; i++) { |
| | | if (globSegments[i] === '*') { |
| | | segments[i] = '*'; |
| | | } |
| | | } |
| | | |
| | | return segments.join('') === globSegments.join(''); |
| | | } |
| | | |
| | | |
| | | // Implicit root state that is always active |
| | | root = registerState({ |
| | | name: '', |
| | | url: '^', |
| | | views: null, |
| | | 'abstract': true |
| | | }); |
| | | root.navigable = null; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$stateProvider#decorator |
| | | * @methodOf ui.router.state.$stateProvider |
| | | * |
| | | * @description |
| | | * Allows you to extend (carefully) or override (at your own peril) the |
| | | * `stateBuilder` object used internally by `$stateProvider`. This can be used |
| | | * to add custom functionality to ui-router, for example inferring templateUrl |
| | | * based on the state name. |
| | | * |
| | | * When passing only a name, it returns the current (original or decorated) builder |
| | | * function that matches `name`. |
| | | * |
| | | * The builder functions that can be decorated are listed below. Though not all |
| | | * necessarily have a good use case for decoration, that is up to you to decide. |
| | | * |
| | | * In addition, users can attach custom decorators, which will generate new |
| | | * properties within the state's internal definition. There is currently no clear |
| | | * use-case for this beyond accessing internal states (i.e. $state.$current), |
| | | * however, expect this to become increasingly relevant as we introduce additional |
| | | * meta-programming features. |
| | | * |
| | | * **Warning**: Decorators should not be interdependent because the order of |
| | | * execution of the builder functions in non-deterministic. Builder functions |
| | | * should only be dependent on the state definition object and super function. |
| | | * |
| | | * |
| | | * Existing builder functions and current return values: |
| | | * |
| | | * - **parent** `{object}` - returns the parent state object. |
| | | * - **data** `{object}` - returns state data, including any inherited data that is not |
| | | * overridden by own values (if any). |
| | | * - **url** `{object}` - returns a {link ui.router.util.type:UrlMatcher} or null. |
| | | * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is |
| | | * navigable). |
| | | * - **params** `{object}` - returns an array of state params that are ensured to |
| | | * be a super-set of parent's params. |
| | | * - **views** `{object}` - returns a views object where each key is an absolute view |
| | | * name (i.e. "viewName@stateName") and each value is the config object |
| | | * (template, controller) for the view. Even when you don't use the views object |
| | | * explicitly on a state config, one is still created for you internally. |
| | | * So by decorating this builder function you have access to decorating template |
| | | * and controller properties. |
| | | * - **ownParams** `{object}` - returns an array of params that belong to the state, |
| | | * not including any params defined by ancestor states. |
| | | * - **path** `{string}` - returns the full path from the root down to this state. |
| | | * Needed for state activation. |
| | | * - **includes** `{object}` - returns an object that includes every state that |
| | | * would pass a '$state.includes()' test. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * // Override the internal 'views' builder with a function that takes the state |
| | | * // definition, and a reference to the internal function being overridden: |
| | | * $stateProvider.decorator('views', function ($state, parent) { |
| | | * var result = {}, |
| | | * views = parent(state); |
| | | * |
| | | * angular.forEach(view, function (config, name) { |
| | | * var autoName = (state.name + '.' + name).replace('.', '/'); |
| | | * config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html'; |
| | | * result[name] = config; |
| | | * }); |
| | | * return result; |
| | | * }); |
| | | * |
| | | * $stateProvider.state('home', { |
| | | * views: { |
| | | * 'contact.list': { controller: 'ListController' }, |
| | | * 'contact.item': { controller: 'ItemController' } |
| | | * } |
| | | * }); |
| | | * |
| | | * // ... |
| | | * |
| | | * $state.go('home'); |
| | | * // Auto-populates list and item views with /partials/home/contact/list.html, |
| | | * // and /partials/home/contact/item.html, respectively. |
| | | * </pre> |
| | | * |
| | | * @param {string} name The name of the builder function to decorate. |
| | | * @param {object} func A function that is responsible for decorating the original |
| | | * builder function. The function receives two parameters: |
| | | * |
| | | * - `{object}` - state - The state config object. |
| | | * - `{object}` - super - The original builder function. |
| | | * |
| | | * @return {object} $stateProvider - $stateProvider instance |
| | | */ |
| | | this.decorator = decorator; |
| | | function decorator(name, func) { |
| | | /*jshint validthis: true */ |
| | | if (isString(name) && !isDefined(func)) { |
| | | return stateBuilder[name]; |
| | | } |
| | | if (!isFunction(func) || !isString(name)) { |
| | | return this; |
| | | } |
| | | if (stateBuilder[name] && !stateBuilder.$delegates[name]) { |
| | | stateBuilder.$delegates[name] = stateBuilder[name]; |
| | | } |
| | | stateBuilder[name] = func; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$stateProvider#state |
| | | * @methodOf ui.router.state.$stateProvider |
| | | * |
| | | * @description |
| | | * Registers a state configuration under a given state name. The stateConfig object |
| | | * has the following acceptable properties. |
| | | * |
| | | * <a id='template'></a> |
| | | * |
| | | * - **`template`** - {string|function=} - html template as a string or a function that returns |
| | | * an html template as a string which should be used by the uiView directives. This property |
| | | * takes precedence over templateUrl. |
| | | * |
| | | * If `template` is a function, it will be called with the following parameters: |
| | | * |
| | | * - {array.<object>} - state parameters extracted from the current $location.path() by |
| | | * applying the current state |
| | | * |
| | | * <a id='templateUrl'></a> |
| | | * |
| | | * - **`templateUrl`** - {string|function=} - path or function that returns a path to an html |
| | | * template that should be used by uiView. |
| | | * |
| | | * If `templateUrl` is a function, it will be called with the following parameters: |
| | | * |
| | | * - {array.<object>} - state parameters extracted from the current $location.path() by |
| | | * applying the current state |
| | | * |
| | | * <a id='templateProvider'></a> |
| | | * |
| | | * - **`templateProvider`** - {function=} - Provider function that returns HTML content |
| | | * string. |
| | | * |
| | | * <a id='controller'></a> |
| | | * |
| | | * - **`controller`** - {string|function=} - Controller fn that should be associated with newly |
| | | * related scope or the name of a registered controller if passed as a string. |
| | | * |
| | | * <a id='controllerProvider'></a> |
| | | * |
| | | * - **`controllerProvider`** - {function=} - Injectable provider function that returns |
| | | * the actual controller or string. |
| | | * |
| | | * <a id='controllerAs'></a> |
| | | * |
| | | * - **`controllerAs`** – {string=} – A controller alias name. If present the controller will be |
| | | * published to scope under the controllerAs name. |
| | | * |
| | | * <a id='resolve'></a> |
| | | * |
| | | * - **`resolve`** - {object.<string, function>=} - An optional map of dependencies which |
| | | * should be injected into the controller. If any of these dependencies are promises, |
| | | * the router will wait for them all to be resolved or one to be rejected before the |
| | | * controller is instantiated. If all the promises are resolved successfully, the values |
| | | * of the resolved promises are injected and $stateChangeSuccess event is fired. If any |
| | | * of the promises are rejected the $stateChangeError event is fired. The map object is: |
| | | * |
| | | * - key - {string}: name of dependency to be injected into controller |
| | | * - factory - {string|function}: If string then it is alias for service. Otherwise if function, |
| | | * it is injected and return value it treated as dependency. If result is a promise, it is |
| | | * resolved before its value is injected into controller. |
| | | * |
| | | * <a id='url'></a> |
| | | * |
| | | * - **`url`** - {string=} - A url with optional parameters. When a state is navigated or |
| | | * transitioned to, the `$stateParams` service will be populated with any |
| | | * parameters that were passed. |
| | | * |
| | | * <a id='params'></a> |
| | | * |
| | | * - **`params`** - {object=} - An array of parameter names or regular expressions. Only |
| | | * use this within a state if you are not using url. Otherwise you can specify your |
| | | * parameters within the url. When a state is navigated or transitioned to, the |
| | | * $stateParams service will be populated with any parameters that were passed. |
| | | * |
| | | * <a id='views'></a> |
| | | * |
| | | * - **`views`** - {object=} - Use the views property to set up multiple views or to target views |
| | | * manually/explicitly. |
| | | * |
| | | * <a id='abstract'></a> |
| | | * |
| | | * - **`abstract`** - {boolean=} - An abstract state will never be directly activated, |
| | | * but can provide inherited properties to its common children states. |
| | | * |
| | | * <a id='onEnter'></a> |
| | | * |
| | | * - **`onEnter`** - {object=} - Callback function for when a state is entered. Good way |
| | | * to trigger an action or dispatch an event, such as opening a dialog. |
| | | * |
| | | * <a id='onExit'></a> |
| | | * |
| | | * - **`onExit`** - {object=} - Callback function for when a state is exited. Good way to |
| | | * trigger an action or dispatch an event, such as opening a dialog. |
| | | * |
| | | * <a id='reloadOnSearch'></a> |
| | | * |
| | | * - **`reloadOnSearch = true`** - {boolean=} - If `false`, will not retrigger the same state |
| | | * just because a search/query parameter has changed (via $location.search() or $location.hash()). |
| | | * Useful for when you'd like to modify $location.search() without triggering a reload. |
| | | * |
| | | * <a id='data'></a> |
| | | * |
| | | * - **`data`** - {object=} - Arbitrary data object, useful for custom configuration. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * // Some state name examples |
| | | * |
| | | * // stateName can be a single top-level name (must be unique). |
| | | * $stateProvider.state("home", {}); |
| | | * |
| | | * // Or it can be a nested state name. This state is a child of the |
| | | * // above "home" state. |
| | | * $stateProvider.state("home.newest", {}); |
| | | * |
| | | * // Nest states as deeply as needed. |
| | | * $stateProvider.state("home.newest.abc.xyz.inception", {}); |
| | | * |
| | | * // state() returns $stateProvider, so you can chain state declarations. |
| | | * $stateProvider |
| | | * .state("home", {}) |
| | | * .state("about", {}) |
| | | * .state("contacts", {}); |
| | | * </pre> |
| | | * |
| | | * @param {string} name A unique state name, e.g. "home", "about", "contacts". |
| | | * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". |
| | | * @param {object} definition State configuration object. |
| | | */ |
| | | this.state = state; |
| | | function state(name, definition) { |
| | | /*jshint validthis: true */ |
| | | if (isObject(name)) definition = name; |
| | | else definition.name = name; |
| | | registerState(definition); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.state.$state |
| | | * |
| | | * @requires $rootScope |
| | | * @requires $q |
| | | * @requires ui.router.state.$view |
| | | * @requires $injector |
| | | * @requires ui.router.util.$resolve |
| | | * @requires ui.router.state.$stateParams |
| | | * |
| | | * @property {object} params A param object, e.g. {sectionId: section.id)}, that |
| | | * you'd like to test against the current active state. |
| | | * @property {object} current A reference to the state's config object. However |
| | | * you passed it in. Useful for accessing custom data. |
| | | * @property {object} transition Currently pending transition. A promise that'll |
| | | * resolve or reject. |
| | | * |
| | | * @description |
| | | * `$state` service is responsible for representing states as well as transitioning |
| | | * between them. It also provides interfaces to ask for current state or even states |
| | | * you're coming from. |
| | | */ |
| | | // $urlRouter is injected just to ensure it gets instantiated |
| | | this.$get = $get; |
| | | $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$location', '$urlRouter', '$browser']; |
| | | function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $location, $urlRouter, $browser) { |
| | | |
| | | var TransitionSuperseded = $q.reject(new Error('transition superseded')); |
| | | var TransitionPrevented = $q.reject(new Error('transition prevented')); |
| | | var TransitionAborted = $q.reject(new Error('transition aborted')); |
| | | var TransitionFailed = $q.reject(new Error('transition failed')); |
| | | var currentLocation = $location.url(); |
| | | var baseHref = $browser.baseHref(); |
| | | |
| | | function syncUrl() { |
| | | if ($location.url() !== currentLocation) { |
| | | $location.url(currentLocation); |
| | | $location.replace(); |
| | | } |
| | | } |
| | | |
| | | root.locals = { resolve: null, globals: { $stateParams: {} } }; |
| | | $state = { |
| | | params: {}, |
| | | current: root.self, |
| | | $current: root, |
| | | transition: null |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#reload |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired, |
| | | * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon). |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app angular.module('app', ['ui.router']); |
| | | * |
| | | * app.controller('ctrl', function ($scope, $state) { |
| | | * $scope.reload = function(){ |
| | | * $state.reload(); |
| | | * } |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * `reload()` is just an alias for: |
| | | * <pre> |
| | | * $state.transitionTo($state.current, $stateParams, { |
| | | * reload: true, inherit: false, notify: false |
| | | * }); |
| | | * </pre> |
| | | */ |
| | | $state.reload = function reload() { |
| | | $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: false }); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#go |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Convenience method for transitioning to a new state. `$state.go` calls |
| | | * `$state.transitionTo` internally but automatically sets options to |
| | | * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. |
| | | * This allows you to easily use an absolute or relative to path and specify |
| | | * only the parameters you'd like to update (while letting unspecified parameters |
| | | * inherit from the currently active ancestor states). |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router']); |
| | | * |
| | | * app.controller('ctrl', function ($scope, $state) { |
| | | * $scope.changeState = function () { |
| | | * $state.go('contact.detail'); |
| | | * }; |
| | | * }); |
| | | * </pre> |
| | | * <img src='../ngdoc_assets/StateGoExamples.png'/> |
| | | * |
| | | * @param {string} to Absolute state name or relative state path. Some examples: |
| | | * |
| | | * - `$state.go('contact.detail')` - will go to the `contact.detail` state |
| | | * - `$state.go('^')` - will go to a parent state |
| | | * - `$state.go('^.sibling')` - will go to a sibling state |
| | | * - `$state.go('.child.grandchild')` - will go to grandchild state |
| | | * |
| | | * @param {object=} params A map of the parameters that will be sent to the state, |
| | | * will populate $stateParams. Any parameters that are not specified will be inherited from currently |
| | | * defined parameters. This allows, for example, going to a sibling state that shares parameters |
| | | * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. |
| | | * transitioning to a sibling will get you the parameters for all parents, transitioning to a child |
| | | * will get you all current parameters, etc. |
| | | * @param {object=} options Options object. The options are: |
| | | * |
| | | * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` |
| | | * will not. If string, must be `"replace"`, which will update url and also replace last history record. |
| | | * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. |
| | | * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), |
| | | * defines which state to be relative from. |
| | | * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. |
| | | * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params |
| | | * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd |
| | | * use this when you want to force a reload when *everything* is the same, including search params. |
| | | * |
| | | * @returns {promise} A promise representing the state of the new transition. |
| | | * |
| | | * Possible success values: |
| | | * |
| | | * - $state.current |
| | | * |
| | | * <br/>Possible rejection values: |
| | | * |
| | | * - 'transition superseded' - when a newer transition has been started after this one |
| | | * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener |
| | | * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or |
| | | * when a `$stateNotFound` `event.retry` promise errors. |
| | | * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. |
| | | * - *resolve error* - when an error has occurred with a `resolve` |
| | | * |
| | | */ |
| | | $state.go = function go(to, params, options) { |
| | | return this.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options)); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#transitionTo |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} |
| | | * uses `transitionTo` internally. `$state.go` is recommended in most situations. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router']); |
| | | * |
| | | * app.controller('ctrl', function ($scope, $state) { |
| | | * $scope.changeState = function () { |
| | | * $state.transitionTo('contact.detail'); |
| | | * }; |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * @param {string} to State name. |
| | | * @param {object=} toParams A map of the parameters that will be sent to the state, |
| | | * will populate $stateParams. |
| | | * @param {object=} options Options object. The options are: |
| | | * |
| | | * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` |
| | | * will not. If string, must be `"replace"`, which will update url and also replace last history record. |
| | | * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. |
| | | * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), |
| | | * defines which state to be relative from. |
| | | * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. |
| | | * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params |
| | | * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd |
| | | * use this when you want to force a reload when *everything* is the same, including search params. |
| | | * |
| | | * @returns {promise} A promise representing the state of the new transition. See |
| | | * {@link ui.router.state.$state#methods_go $state.go}. |
| | | */ |
| | | $state.transitionTo = function transitionTo(to, toParams, options) { |
| | | toParams = toParams || {}; |
| | | options = extend({ |
| | | location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false |
| | | }, options || {}); |
| | | |
| | | var from = $state.$current, fromParams = $state.params, fromPath = from.path; |
| | | var evt, toState = findState(to, options.relative); |
| | | |
| | | if (!isDefined(toState)) { |
| | | // Broadcast not found event and abort the transition if prevented |
| | | var redirect = { to: to, toParams: toParams, options: options }; |
| | | |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.$state#$stateNotFound |
| | | * @eventOf ui.router.state.$state |
| | | * @eventType broadcast on root scope |
| | | * @description |
| | | * Fired when a requested state **cannot be found** using the provided state name during transition. |
| | | * The event is broadcast allowing any handlers a single chance to deal with the error (usually by |
| | | * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler, |
| | | * you can see its three properties in the example. You can use `event.preventDefault()` to abort the |
| | | * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value. |
| | | * |
| | | * @param {Object} event Event object. |
| | | * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties. |
| | | * @param {State} fromState Current state object. |
| | | * @param {Object} fromParams Current state params. |
| | | * |
| | | * @example |
| | | * |
| | | * <pre> |
| | | * // somewhere, assume lazy.state has not been defined |
| | | * $state.go("lazy.state", {a:1, b:2}, {inherit:false}); |
| | | * |
| | | * // somewhere else |
| | | * $scope.$on('$stateNotFound', |
| | | * function(event, unfoundState, fromState, fromParams){ |
| | | * console.log(unfoundState.to); // "lazy.state" |
| | | * console.log(unfoundState.toParams); // {a:1, b:2} |
| | | * console.log(unfoundState.options); // {inherit:false} + default options |
| | | * }) |
| | | * </pre> |
| | | */ |
| | | evt = $rootScope.$broadcast('$stateNotFound', redirect, from.self, fromParams); |
| | | if (evt.defaultPrevented) { |
| | | syncUrl(); |
| | | return TransitionAborted; |
| | | } |
| | | |
| | | // Allow the handler to return a promise to defer state lookup retry |
| | | if (evt.retry) { |
| | | if (options.$retry) { |
| | | syncUrl(); |
| | | return TransitionFailed; |
| | | } |
| | | var retryTransition = $state.transition = $q.when(evt.retry); |
| | | retryTransition.then(function() { |
| | | if (retryTransition !== $state.transition) return TransitionSuperseded; |
| | | redirect.options.$retry = true; |
| | | return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); |
| | | }, function() { |
| | | return TransitionAborted; |
| | | }); |
| | | syncUrl(); |
| | | return retryTransition; |
| | | } |
| | | |
| | | // Always retry once if the $stateNotFound was not prevented |
| | | // (handles either redirect changed or state lazy-definition) |
| | | to = redirect.to; |
| | | toParams = redirect.toParams; |
| | | options = redirect.options; |
| | | toState = findState(to, options.relative); |
| | | if (!isDefined(toState)) { |
| | | if (options.relative) throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); |
| | | throw new Error("No such state '" + to + "'"); |
| | | } |
| | | } |
| | | if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); |
| | | if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); |
| | | to = toState; |
| | | |
| | | var toPath = to.path; |
| | | |
| | | // Starting from the root of the path, keep all levels that haven't changed |
| | | var keep, state, locals = root.locals, toLocals = []; |
| | | for (keep = 0, state = toPath[keep]; |
| | | state && state === fromPath[keep] && equalForKeys(toParams, fromParams, state.ownParams) && !options.reload; |
| | | keep++, state = toPath[keep]) { |
| | | locals = toLocals[keep] = state.locals; |
| | | } |
| | | |
| | | // If we're going to the same state and all locals are kept, we've got nothing to do. |
| | | // But clear 'transition', as we still want to cancel any other pending transitions. |
| | | // TODO: We may not want to bump 'transition' if we're called from a location change that we've initiated ourselves, |
| | | // because we might accidentally abort a legitimate transition initiated from code? |
| | | if (shouldTriggerReload(to, from, locals, options) ) { |
| | | if ( to.self.reloadOnSearch !== false ) |
| | | syncUrl(); |
| | | $state.transition = null; |
| | | return $q.when($state.current); |
| | | } |
| | | |
| | | // Normalize/filter parameters before we pass them to event handlers etc. |
| | | toParams = normalize(to.params, toParams || {}); |
| | | |
| | | // Broadcast start event and cancel the transition if requested |
| | | if (options.notify) { |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.$state#$stateChangeStart |
| | | * @eventOf ui.router.state.$state |
| | | * @eventType broadcast on root scope |
| | | * @description |
| | | * Fired when the state transition **begins**. You can use `event.preventDefault()` |
| | | * to prevent the transition from happening and then the transition promise will be |
| | | * rejected with a `'transition prevented'` value. |
| | | * |
| | | * @param {Object} event Event object. |
| | | * @param {State} toState The state being transitioned to. |
| | | * @param {Object} toParams The params supplied to the `toState`. |
| | | * @param {State} fromState The current state, pre-transition. |
| | | * @param {Object} fromParams The params supplied to the `fromState`. |
| | | * |
| | | * @example |
| | | * |
| | | * <pre> |
| | | * $rootScope.$on('$stateChangeStart', |
| | | * function(event, toState, toParams, fromState, fromParams){ |
| | | * event.preventDefault(); |
| | | * // transitionTo() promise will be rejected with |
| | | * // a 'transition prevented' error |
| | | * }) |
| | | * </pre> |
| | | */ |
| | | evt = $rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams); |
| | | if (evt.defaultPrevented) { |
| | | syncUrl(); |
| | | return TransitionPrevented; |
| | | } |
| | | } |
| | | |
| | | // Resolve locals for the remaining states, but don't update any global state just |
| | | // yet -- if anything fails to resolve the current state needs to remain untouched. |
| | | // We also set up an inheritance chain for the locals here. This allows the view directive |
| | | // to quickly look up the correct definition for each view in the current state. Even |
| | | // though we create the locals object itself outside resolveState(), it is initially |
| | | // empty and gets filled asynchronously. We need to keep track of the promise for the |
| | | // (fully resolved) current locals, and pass this down the chain. |
| | | var resolved = $q.when(locals); |
| | | for (var l=keep; l<toPath.length; l++, state=toPath[l]) { |
| | | locals = toLocals[l] = inherit(locals); |
| | | resolved = resolveState(state, toParams, state===to, resolved, locals); |
| | | } |
| | | |
| | | // Once everything is resolved, we are ready to perform the actual transition |
| | | // and return a promise for the new state. We also keep track of what the |
| | | // current promise is, so that we can detect overlapping transitions and |
| | | // keep only the outcome of the last transition. |
| | | var transition = $state.transition = resolved.then(function () { |
| | | var l, entering, exiting; |
| | | |
| | | if ($state.transition !== transition) return TransitionSuperseded; |
| | | |
| | | // Exit 'from' states not kept |
| | | for (l=fromPath.length-1; l>=keep; l--) { |
| | | exiting = fromPath[l]; |
| | | if (exiting.self.onExit) { |
| | | $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); |
| | | } |
| | | exiting.locals = null; |
| | | } |
| | | |
| | | // Enter 'to' states not kept |
| | | for (l=keep; l<toPath.length; l++) { |
| | | entering = toPath[l]; |
| | | entering.locals = toLocals[l]; |
| | | if (entering.self.onEnter) { |
| | | $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); |
| | | } |
| | | } |
| | | |
| | | // Run it again, to catch any transitions in callbacks |
| | | if ($state.transition !== transition) return TransitionSuperseded; |
| | | |
| | | // Update globals in $state |
| | | $state.$current = to; |
| | | $state.current = to.self; |
| | | $state.params = toParams; |
| | | copy($state.params, $stateParams); |
| | | $state.transition = null; |
| | | |
| | | // Update $location |
| | | var toNav = to.navigable; |
| | | if (options.location && toNav) { |
| | | $location.url(toNav.url.format(toNav.locals.globals.$stateParams)); |
| | | |
| | | if (options.location === 'replace') { |
| | | $location.replace(); |
| | | } |
| | | } |
| | | |
| | | if (options.notify) { |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.$state#$stateChangeSuccess |
| | | * @eventOf ui.router.state.$state |
| | | * @eventType broadcast on root scope |
| | | * @description |
| | | * Fired once the state transition is **complete**. |
| | | * |
| | | * @param {Object} event Event object. |
| | | * @param {State} toState The state being transitioned to. |
| | | * @param {Object} toParams The params supplied to the `toState`. |
| | | * @param {State} fromState The current state, pre-transition. |
| | | * @param {Object} fromParams The params supplied to the `fromState`. |
| | | */ |
| | | $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams); |
| | | } |
| | | currentLocation = $location.url(); |
| | | |
| | | return $state.current; |
| | | }, function (error) { |
| | | if ($state.transition !== transition) return TransitionSuperseded; |
| | | |
| | | $state.transition = null; |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.$state#$stateChangeError |
| | | * @eventOf ui.router.state.$state |
| | | * @eventType broadcast on root scope |
| | | * @description |
| | | * Fired when an **error occurs** during transition. It's important to note that if you |
| | | * have any errors in your resolve functions (javascript errors, non-existent services, etc) |
| | | * they will not throw traditionally. You must listen for this $stateChangeError event to |
| | | * catch **ALL** errors. |
| | | * |
| | | * @param {Object} event Event object. |
| | | * @param {State} toState The state being transitioned to. |
| | | * @param {Object} toParams The params supplied to the `toState`. |
| | | * @param {State} fromState The current state, pre-transition. |
| | | * @param {Object} fromParams The params supplied to the `fromState`. |
| | | * @param {Error} error The resolve error object. |
| | | */ |
| | | $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error); |
| | | syncUrl(); |
| | | |
| | | return $q.reject(error); |
| | | }); |
| | | |
| | | return transition; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#is |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, |
| | | * but only checks for the full state name. If params is supplied then it will be |
| | | * tested for strict equality against the current active params object, so all params |
| | | * must match with none missing and no extras. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * $state.is('contact.details.item'); // returns true |
| | | * $state.is(contactDetailItemStateObject); // returns true |
| | | * |
| | | * // everything else would return false |
| | | * </pre> |
| | | * |
| | | * @param {string|object} stateName The state name or state object you'd like to check. |
| | | * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like |
| | | * to test against the current active state. |
| | | * @returns {boolean} Returns true if it is the state. |
| | | */ |
| | | $state.is = function is(stateOrName, params) { |
| | | var state = findState(stateOrName); |
| | | |
| | | if (!isDefined(state)) { |
| | | return undefined; |
| | | } |
| | | |
| | | if ($state.$current !== state) { |
| | | return false; |
| | | } |
| | | |
| | | return isDefined(params) && params !== null ? angular.equals($stateParams, params) : true; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#includes |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * A method to determine if the current active state is equal to or is the child of the |
| | | * state stateName. If any params are passed then they will be tested for a match as well. |
| | | * Not all the parameters need to be passed, just the ones you'd like to test for equality. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * $state.$current.name = 'contacts.details.item'; |
| | | * |
| | | * $state.includes("contacts"); // returns true |
| | | * $state.includes("contacts.details"); // returns true |
| | | * $state.includes("contacts.details.item"); // returns true |
| | | * $state.includes("contacts.list"); // returns false |
| | | * $state.includes("about"); // returns false |
| | | * </pre> |
| | | * |
| | | * @description |
| | | * Basic globing patterns will also work. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * $state.$current.name = 'contacts.details.item.url'; |
| | | * |
| | | * $state.includes("*.details.*.*"); // returns true |
| | | * $state.includes("*.details.**"); // returns true |
| | | * $state.includes("**.item.**"); // returns true |
| | | * $state.includes("*.details.item.url"); // returns true |
| | | * $state.includes("*.details.*.url"); // returns true |
| | | * $state.includes("*.details.*"); // returns false |
| | | * $state.includes("item.**"); // returns false |
| | | * </pre> |
| | | * |
| | | * @param {string} stateOrName A partial name to be searched for within the current state name. |
| | | * @param {object} params A param object, e.g. `{sectionId: section.id}`, |
| | | * that you'd like to test against the current active state. |
| | | * @returns {boolean} Returns true if it does include the state |
| | | */ |
| | | |
| | | $state.includes = function includes(stateOrName, params) { |
| | | if (isString(stateOrName) && isGlob(stateOrName)) { |
| | | if (doesStateMatchGlob(stateOrName)) { |
| | | stateOrName = $state.$current.name; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | var state = findState(stateOrName); |
| | | if (!isDefined(state)) { |
| | | return undefined; |
| | | } |
| | | |
| | | if (!isDefined($state.$current.includes[state.name])) { |
| | | return false; |
| | | } |
| | | |
| | | var validParams = true; |
| | | angular.forEach(params, function(value, key) { |
| | | if (!isDefined($stateParams[key]) || $stateParams[key] !== value) { |
| | | validParams = false; |
| | | } |
| | | }); |
| | | return validParams; |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#href |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * A url generation method that returns the compiled url for the given state populated with the given params. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob"); |
| | | * </pre> |
| | | * |
| | | * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. |
| | | * @param {object=} params An object of parameter values to fill the state's required parameters. |
| | | * @param {object=} options Options object. The options are: |
| | | * |
| | | * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the |
| | | * first parameter, then the constructed href url will be built from the first navigable ancestor (aka |
| | | * ancestor with a valid url). |
| | | * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. |
| | | * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), |
| | | * defines which state to be relative from. |
| | | * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". |
| | | * |
| | | * @returns {string} compiled state url |
| | | */ |
| | | $state.href = function href(stateOrName, params, options) { |
| | | options = extend({ lossy: true, inherit: false, absolute: false, relative: $state.$current }, options || {}); |
| | | var state = findState(stateOrName, options.relative); |
| | | if (!isDefined(state)) return null; |
| | | |
| | | params = inheritParams($stateParams, params || {}, $state.$current, state); |
| | | var nav = (state && options.lossy) ? state.navigable : state; |
| | | var url = (nav && nav.url) ? nav.url.format(normalize(state.params, params || {})) : null; |
| | | if (!$locationProvider.html5Mode() && url) { |
| | | url = "#" + $locationProvider.hashPrefix() + url; |
| | | } |
| | | |
| | | if (baseHref !== '/') { |
| | | if ($locationProvider.html5Mode()) { |
| | | url = baseHref.slice(0, -1) + url; |
| | | } else if (options.absolute){ |
| | | url = baseHref.slice(1) + url; |
| | | } |
| | | } |
| | | |
| | | if (options.absolute && url) { |
| | | url = $location.protocol() + '://' + |
| | | $location.host() + |
| | | ($location.port() == 80 || $location.port() == 443 ? '' : ':' + $location.port()) + |
| | | (!$locationProvider.html5Mode() && url ? '/' : '') + |
| | | url; |
| | | } |
| | | return url; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$state#get |
| | | * @methodOf ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Returns the state configuration object for any specific state or all states. |
| | | * |
| | | * @param {string|object=} stateOrName If provided, will only get the config for |
| | | * the requested state. If not provided, returns an array of ALL state configs. |
| | | * @returns {object|array} State configuration object or array of all objects. |
| | | */ |
| | | $state.get = function (stateOrName, context) { |
| | | if (!isDefined(stateOrName)) { |
| | | var list = []; |
| | | forEach(states, function(state) { list.push(state.self); }); |
| | | return list; |
| | | } |
| | | var state = findState(stateOrName, context); |
| | | return (state && state.self) ? state.self : null; |
| | | }; |
| | | |
| | | function resolveState(state, params, paramsAreFiltered, inherited, dst) { |
| | | // Make a restricted $stateParams with only the parameters that apply to this state if |
| | | // necessary. In addition to being available to the controller and onEnter/onExit callbacks, |
| | | // we also need $stateParams to be available for any $injector calls we make during the |
| | | // dependency resolution process. |
| | | var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params, params); |
| | | var locals = { $stateParams: $stateParams }; |
| | | |
| | | // Resolve 'global' dependencies for the state, i.e. those not specific to a view. |
| | | // We're also including $stateParams in this; that way the parameters are restricted |
| | | // to the set that should be visible to the state, and are independent of when we update |
| | | // the global $state and $stateParams values. |
| | | dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); |
| | | var promises = [ dst.resolve.then(function (globals) { |
| | | dst.globals = globals; |
| | | }) ]; |
| | | if (inherited) promises.push(inherited); |
| | | |
| | | // Resolve template and dependencies for all views. |
| | | forEach(state.views, function (view, name) { |
| | | var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {}); |
| | | injectables.$template = [ function () { |
| | | return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: false }) || ''; |
| | | }]; |
| | | |
| | | promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) { |
| | | // References to the controller (only instantiated at link time) |
| | | if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { |
| | | var injectLocals = angular.extend({}, injectables, locals); |
| | | result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); |
| | | } else { |
| | | result.$$controller = view.controller; |
| | | } |
| | | // Provide access to the state itself for internal use |
| | | result.$$state = state; |
| | | result.$$controllerAs = view.controllerAs; |
| | | dst[name] = result; |
| | | })); |
| | | }); |
| | | |
| | | // Wait for all the promises and then return the activation object |
| | | return $q.all(promises).then(function (values) { |
| | | return dst; |
| | | }); |
| | | } |
| | | |
| | | return $state; |
| | | } |
| | | |
| | | function shouldTriggerReload(to, from, locals, options) { |
| | | if ( to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false)) ) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | angular.module('ui.router.state') |
| | | .value('$stateParams', {}) |
| | | .provider('$state', $StateProvider); |
| | | |
| | | |
| | | $ViewProvider.$inject = []; |
| | | function $ViewProvider() { |
| | | |
| | | this.$get = $get; |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.state.$view |
| | | * |
| | | * @requires ui.router.util.$templateFactory |
| | | * @requires $rootScope |
| | | * |
| | | * @description |
| | | * |
| | | */ |
| | | $get.$inject = ['$rootScope', '$templateFactory']; |
| | | function $get( $rootScope, $templateFactory) { |
| | | return { |
| | | // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$view#load |
| | | * @methodOf ui.router.state.$view |
| | | * |
| | | * @description |
| | | * |
| | | * @param {string} name name |
| | | * @param {object} options option object. |
| | | */ |
| | | load: function load(name, options) { |
| | | var result, defaults = { |
| | | template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} |
| | | }; |
| | | options = extend(defaults, options); |
| | | |
| | | if (options.view) { |
| | | result = $templateFactory.fromConfig(options.view, options.params, options.locals); |
| | | } |
| | | if (result && options.notify) { |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.$state#$viewContentLoading |
| | | * @eventOf ui.router.state.$view |
| | | * @eventType broadcast on root scope |
| | | * @description |
| | | * |
| | | * Fired once the view **begins loading**, *before* the DOM is rendered. |
| | | * |
| | | * @param {Object} event Event object. |
| | | * @param {Object} viewConfig The view config properties (template, controller, etc). |
| | | * |
| | | * @example |
| | | * |
| | | * <pre> |
| | | * $scope.$on('$viewContentLoading', |
| | | * function(event, viewConfig){ |
| | | * // Access to all the view config properties. |
| | | * // and one special property 'targetView' |
| | | * // viewConfig.targetView |
| | | * }); |
| | | * </pre> |
| | | */ |
| | | $rootScope.$broadcast('$viewContentLoading', options); |
| | | } |
| | | return result; |
| | | } |
| | | }; |
| | | } |
| | | } |
| | | |
| | | angular.module('ui.router.state').provider('$view', $ViewProvider); |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.state.$uiViewScrollProvider |
| | | * |
| | | * @description |
| | | * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. |
| | | */ |
| | | function $ViewScrollProvider() { |
| | | |
| | | var useAnchorScroll = false; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll |
| | | * @methodOf ui.router.state.$uiViewScrollProvider |
| | | * |
| | | * @description |
| | | * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for |
| | | * scrolling based on the url anchor. |
| | | */ |
| | | this.useAnchorScroll = function () { |
| | | useAnchorScroll = true; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name ui.router.state.$uiViewScroll |
| | | * |
| | | * @requires $anchorScroll |
| | | * @requires $timeout |
| | | * |
| | | * @description |
| | | * When called with a jqLite element, it scrolls the element into view (after a |
| | | * `$timeout` so the DOM has time to refresh). |
| | | * |
| | | * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, |
| | | * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. |
| | | */ |
| | | this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { |
| | | if (useAnchorScroll) { |
| | | return $anchorScroll; |
| | | } |
| | | |
| | | return function ($element) { |
| | | $timeout(function () { |
| | | $element[0].scrollIntoView(); |
| | | }, 0, false); |
| | | }; |
| | | }]; |
| | | } |
| | | |
| | | angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); |
| | | |
| | | /** |
| | | * @ngdoc directive |
| | | * @name ui.router.state.directive:ui-view |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * @requires $compile |
| | | * @requires $controller |
| | | * @requires $injector |
| | | * @requires ui.router.state.$uiViewScroll |
| | | * @requires $document |
| | | * |
| | | * @restrict ECA |
| | | * |
| | | * @description |
| | | * The ui-view directive tells $state where to place your templates. |
| | | * |
| | | * @param {string=} ui-view A view name. The name should be unique amongst the other views in the |
| | | * same state. You can have views of the same name that live in different states. |
| | | * |
| | | * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window |
| | | * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll |
| | | * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you |
| | | * scroll ui-view elements into view when they are populated during a state activation. |
| | | * |
| | | * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) |
| | | * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* |
| | | * |
| | | * @param {string=} onload Expression to evaluate whenever the view updates. |
| | | * |
| | | * @example |
| | | * A view can be unnamed or named. |
| | | * <pre> |
| | | * <!-- Unnamed --> |
| | | * <div ui-view></div> |
| | | * |
| | | * <!-- Named --> |
| | | * <div ui-view="viewName"></div> |
| | | * </pre> |
| | | * |
| | | * You can only have one unnamed view within any template (or root html). If you are only using a |
| | | * single view and it is unnamed then you can populate it like so: |
| | | * <pre> |
| | | * <div ui-view></div> |
| | | * $stateProvider.state("home", { |
| | | * template: "<h1>HELLO!</h1>" |
| | | * }) |
| | | * </pre> |
| | | * |
| | | * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} |
| | | * config property, by name, in this case an empty name: |
| | | * <pre> |
| | | * $stateProvider.state("home", { |
| | | * views: { |
| | | * "": { |
| | | * template: "<h1>HELLO!</h1>" |
| | | * } |
| | | * } |
| | | * }) |
| | | * </pre> |
| | | * |
| | | * But typically you'll only use the views property if you name your view or have more than one view |
| | | * in the same template. There's not really a compelling reason to name a view if its the only one, |
| | | * but you could if you wanted, like so: |
| | | * <pre> |
| | | * <div ui-view="main"></div> |
| | | * </pre> |
| | | * <pre> |
| | | * $stateProvider.state("home", { |
| | | * views: { |
| | | * "main": { |
| | | * template: "<h1>HELLO!</h1>" |
| | | * } |
| | | * } |
| | | * }) |
| | | * </pre> |
| | | * |
| | | * Really though, you'll use views to set up multiple views: |
| | | * <pre> |
| | | * <div ui-view></div> |
| | | * <div ui-view="chart"></div> |
| | | * <div ui-view="data"></div> |
| | | * </pre> |
| | | * |
| | | * <pre> |
| | | * $stateProvider.state("home", { |
| | | * views: { |
| | | * "": { |
| | | * template: "<h1>HELLO!</h1>" |
| | | * }, |
| | | * "chart": { |
| | | * template: "<chart_thing/>" |
| | | * }, |
| | | * "data": { |
| | | * template: "<data_thing/>" |
| | | * } |
| | | * } |
| | | * }) |
| | | * </pre> |
| | | * |
| | | * Examples for `autoscroll`: |
| | | * |
| | | * <pre> |
| | | * <!-- If autoscroll present with no expression, |
| | | * then scroll ui-view into view --> |
| | | * <ui-view autoscroll/> |
| | | * |
| | | * <!-- If autoscroll present with valid expression, |
| | | * then scroll ui-view into view if expression evaluates to true --> |
| | | * <ui-view autoscroll='true'/> |
| | | * <ui-view autoscroll='false'/> |
| | | * <ui-view autoscroll='scopeVariable'/> |
| | | * </pre> |
| | | */ |
| | | $ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll']; |
| | | function $ViewDirective( $state, $injector, $uiViewScroll) { |
| | | |
| | | function getService() { |
| | | return ($injector.has) ? function(service) { |
| | | return $injector.has(service) ? $injector.get(service) : null; |
| | | } : function(service) { |
| | | try { |
| | | return $injector.get(service); |
| | | } catch (e) { |
| | | return null; |
| | | } |
| | | }; |
| | | } |
| | | |
| | | var service = getService(), |
| | | $animator = service('$animator'), |
| | | $animate = service('$animate'); |
| | | |
| | | // Returns a set of DOM manipulation functions based on which Angular version |
| | | // it should use |
| | | function getRenderer(attrs, scope) { |
| | | var statics = function() { |
| | | return { |
| | | enter: function (element, target, cb) { target.after(element); cb(); }, |
| | | leave: function (element, cb) { element.remove(); cb(); } |
| | | }; |
| | | }; |
| | | |
| | | if ($animate) { |
| | | return { |
| | | enter: function(element, target, cb) { $animate.enter(element, null, target, cb); }, |
| | | leave: function(element, cb) { $animate.leave(element, cb); } |
| | | }; |
| | | } |
| | | |
| | | if ($animator) { |
| | | var animate = $animator && $animator(scope, attrs); |
| | | |
| | | return { |
| | | enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, |
| | | leave: function(element, cb) { animate.leave(element); cb(); } |
| | | }; |
| | | } |
| | | |
| | | return statics(); |
| | | } |
| | | |
| | | var directive = { |
| | | restrict: 'ECA', |
| | | terminal: true, |
| | | priority: 400, |
| | | transclude: 'element', |
| | | compile: function (tElement, tAttrs, $transclude) { |
| | | return function (scope, $element, attrs) { |
| | | var previousEl, currentEl, currentScope, latestLocals, |
| | | onloadExp = attrs.onload || '', |
| | | autoScrollExp = attrs.autoscroll, |
| | | renderer = getRenderer(attrs, scope); |
| | | |
| | | scope.$on('$stateChangeSuccess', function() { |
| | | updateView(false); |
| | | }); |
| | | scope.$on('$viewContentLoading', function() { |
| | | updateView(false); |
| | | }); |
| | | |
| | | updateView(true); |
| | | |
| | | function cleanupLastView() { |
| | | if (previousEl) { |
| | | previousEl.remove(); |
| | | previousEl = null; |
| | | } |
| | | |
| | | if (currentScope) { |
| | | currentScope.$destroy(); |
| | | currentScope = null; |
| | | } |
| | | |
| | | if (currentEl) { |
| | | renderer.leave(currentEl, function() { |
| | | previousEl = null; |
| | | }); |
| | | |
| | | previousEl = currentEl; |
| | | currentEl = null; |
| | | } |
| | | } |
| | | |
| | | function updateView(firstTime) { |
| | | var newScope = scope.$new(), |
| | | name = currentEl && currentEl.data('$uiViewName'), |
| | | previousLocals = name && $state.$current && $state.$current.locals[name]; |
| | | |
| | | if (!firstTime && previousLocals === latestLocals) return; // nothing to do |
| | | |
| | | var clone = $transclude(newScope, function(clone) { |
| | | renderer.enter(clone, $element, function onUiViewEnter() { |
| | | if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { |
| | | $uiViewScroll(clone); |
| | | } |
| | | }); |
| | | cleanupLastView(); |
| | | }); |
| | | |
| | | latestLocals = $state.$current.locals[clone.data('$uiViewName')]; |
| | | |
| | | currentEl = clone; |
| | | currentScope = newScope; |
| | | /** |
| | | * @ngdoc event |
| | | * @name ui.router.state.directive:ui-view#$viewContentLoaded |
| | | * @eventOf ui.router.state.directive:ui-view |
| | | * @eventType emits on ui-view directive scope |
| | | * @description * |
| | | * Fired once the view is **loaded**, *after* the DOM is rendered. |
| | | * |
| | | * @param {Object} event Event object. |
| | | */ |
| | | currentScope.$emit('$viewContentLoaded'); |
| | | currentScope.$eval(onloadExp); |
| | | } |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | return directive; |
| | | } |
| | | |
| | | $ViewDirectiveFill.$inject = ['$compile', '$controller', '$state']; |
| | | function $ViewDirectiveFill ($compile, $controller, $state) { |
| | | return { |
| | | restrict: 'ECA', |
| | | priority: -400, |
| | | compile: function (tElement) { |
| | | var initial = tElement.html(); |
| | | return function (scope, $element, attrs) { |
| | | var name = attrs.uiView || attrs.name || '', |
| | | inherited = $element.inheritedData('$uiView'); |
| | | |
| | | if (name.indexOf('@') < 0) { |
| | | name = name + '@' + (inherited ? inherited.state.name : ''); |
| | | } |
| | | |
| | | $element.data('$uiViewName', name); |
| | | |
| | | var current = $state.$current, |
| | | locals = current && current.locals[name]; |
| | | |
| | | if (! locals) { |
| | | return; |
| | | } |
| | | |
| | | $element.data('$uiView', { name: name, state: locals.$$state }); |
| | | $element.html(locals.$template ? locals.$template : initial); |
| | | |
| | | var link = $compile($element.contents()); |
| | | |
| | | if (locals.$$controller) { |
| | | locals.$scope = scope; |
| | | var controller = $controller(locals.$$controller, locals); |
| | | if (locals.$$controllerAs) { |
| | | scope[locals.$$controllerAs] = controller; |
| | | } |
| | | $element.data('$ngControllerController', controller); |
| | | $element.children().data('$ngControllerController', controller); |
| | | } |
| | | |
| | | link(scope); |
| | | }; |
| | | } |
| | | }; |
| | | } |
| | | |
| | | angular.module('ui.router.state').directive('uiView', $ViewDirective); |
| | | angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); |
| | | |
| | | function parseStateRef(ref) { |
| | | var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); |
| | | if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); |
| | | return { state: parsed[1], paramExpr: parsed[3] || null }; |
| | | } |
| | | |
| | | function stateContext(el) { |
| | | var stateData = el.parent().inheritedData('$uiView'); |
| | | |
| | | if (stateData && stateData.state && stateData.state.name) { |
| | | return stateData.state; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc directive |
| | | * @name ui.router.state.directive:ui-sref |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * @requires $timeout |
| | | * |
| | | * @restrict A |
| | | * |
| | | * @description |
| | | * A directive that binds a link (`<a>` tag) to a state. If the state has an associated |
| | | * URL, the directive will automatically generate & update the `href` attribute via |
| | | * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking |
| | | * the link will trigger a state transition with optional parameters. |
| | | * |
| | | * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be |
| | | * handled natively by the browser. |
| | | * |
| | | * You can also use relative state paths within ui-sref, just like the relative |
| | | * paths passed to `$state.go()`. You just need to be aware that the path is relative |
| | | * to the state that the link lives in, in other words the state that loaded the |
| | | * template containing the link. |
| | | * |
| | | * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} |
| | | * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, |
| | | * and `reload`. |
| | | * |
| | | * @example |
| | | * Here's an example of how you'd use ui-sref and how it would compile. If you have the |
| | | * following template: |
| | | * <pre> |
| | | * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> |
| | | * |
| | | * <ul> |
| | | * <li ng-repeat="contact in contacts"> |
| | | * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a> |
| | | * </li> |
| | | * </ul> |
| | | * </pre> |
| | | * |
| | | * Then the compiled html would be (assuming Html5Mode is off): |
| | | * <pre> |
| | | * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> |
| | | * |
| | | * <ul> |
| | | * <li ng-repeat="contact in contacts"> |
| | | * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a> |
| | | * </li> |
| | | * <li ng-repeat="contact in contacts"> |
| | | * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a> |
| | | * </li> |
| | | * <li ng-repeat="contact in contacts"> |
| | | * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a> |
| | | * </li> |
| | | * </ul> |
| | | * |
| | | * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a> |
| | | * </pre> |
| | | * |
| | | * @param {string} ui-sref 'stateName' can be any valid absolute or relative state |
| | | * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()} |
| | | */ |
| | | $StateRefDirective.$inject = ['$state', '$timeout']; |
| | | function $StateRefDirective($state, $timeout) { |
| | | var allowedOptions = ['location', 'inherit', 'reload']; |
| | | |
| | | return { |
| | | restrict: 'A', |
| | | require: '?^uiSrefActive', |
| | | link: function(scope, element, attrs, uiSrefActive) { |
| | | var ref = parseStateRef(attrs.uiSref); |
| | | var params = null, url = null, base = stateContext(element) || $state.$current; |
| | | var isForm = element[0].nodeName === "FORM"; |
| | | var attr = isForm ? "action" : "href", nav = true; |
| | | |
| | | var options = { |
| | | relative: base |
| | | }; |
| | | var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {}; |
| | | angular.forEach(allowedOptions, function(option) { |
| | | if (option in optionsOverride) { |
| | | options[option] = optionsOverride[option]; |
| | | } |
| | | }); |
| | | |
| | | var update = function(newVal) { |
| | | if (newVal) params = newVal; |
| | | if (!nav) return; |
| | | |
| | | var newHref = $state.href(ref.state, params, options); |
| | | |
| | | if (uiSrefActive) { |
| | | uiSrefActive.$$setStateInfo(ref.state, params); |
| | | } |
| | | if (!newHref) { |
| | | nav = false; |
| | | return false; |
| | | } |
| | | element[0][attr] = newHref; |
| | | }; |
| | | |
| | | if (ref.paramExpr) { |
| | | scope.$watch(ref.paramExpr, function(newVal, oldVal) { |
| | | if (newVal !== params) update(newVal); |
| | | }, true); |
| | | params = scope.$eval(ref.paramExpr); |
| | | } |
| | | update(); |
| | | |
| | | if (isForm) return; |
| | | |
| | | element.bind("click", function(e) { |
| | | var button = e.which || e.button; |
| | | if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) { |
| | | // HACK: This is to allow ng-clicks to be processed before the transition is initiated: |
| | | $timeout(function() { |
| | | $state.go(ref.state, params, options); |
| | | }); |
| | | e.preventDefault(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc directive |
| | | * @name ui.router.state.directive:ui-sref-active |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * @requires ui.router.state.$stateParams |
| | | * @requires $interpolate |
| | | * |
| | | * @restrict A |
| | | * |
| | | * @description |
| | | * A directive working alongside ui-sref to add classes to an element when the |
| | | * related ui-sref directive's state is active, and removing them when it is inactive. |
| | | * The primary use-case is to simplify the special appearance of navigation menus |
| | | * relying on `ui-sref`, by having the "active" state's menu button appear different, |
| | | * distinguishing it from the inactive menu items. |
| | | * |
| | | * @example |
| | | * Given the following template: |
| | | * <pre> |
| | | * <ul> |
| | | * <li ui-sref-active="active" class="item"> |
| | | * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a> |
| | | * </li> |
| | | * </ul> |
| | | * </pre> |
| | | * |
| | | * When the app state is "app.user", and contains the state parameter "user" with value "bilbobaggins", |
| | | * the resulting HTML will appear as (note the 'active' class): |
| | | * <pre> |
| | | * <ul> |
| | | * <li ui-sref-active="active" class="item active"> |
| | | * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a> |
| | | * </li> |
| | | * </ul> |
| | | * </pre> |
| | | * |
| | | * The class name is interpolated **once** during the directives link time (any further changes to the |
| | | * interpolated value are ignored). |
| | | * |
| | | * Multiple classes may be specified in a space-separated format: |
| | | * <pre> |
| | | * <ul> |
| | | * <li ui-sref-active='class1 class2 class3'> |
| | | * <a ui-sref="app.user">link</a> |
| | | * </li> |
| | | * </ul> |
| | | * </pre> |
| | | */ |
| | | $StateActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; |
| | | function $StateActiveDirective($state, $stateParams, $interpolate) { |
| | | return { |
| | | restrict: "A", |
| | | controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { |
| | | var state, params, activeClass; |
| | | |
| | | // There probably isn't much point in $observing this |
| | | activeClass = $interpolate($attrs.uiSrefActive || '', false)($scope); |
| | | |
| | | // Allow uiSref to communicate with uiSrefActive |
| | | this.$$setStateInfo = function(newState, newParams) { |
| | | state = $state.get(newState, stateContext($element)); |
| | | params = newParams; |
| | | update(); |
| | | }; |
| | | |
| | | $scope.$on('$stateChangeSuccess', update); |
| | | |
| | | // Update route state |
| | | function update() { |
| | | if ($state.$current.self === state && matchesParams()) { |
| | | $element.addClass(activeClass); |
| | | } else { |
| | | $element.removeClass(activeClass); |
| | | } |
| | | } |
| | | |
| | | function matchesParams() { |
| | | return !params || equalForKeys(params, $stateParams); |
| | | } |
| | | }] |
| | | }; |
| | | } |
| | | |
| | | angular.module('ui.router.state') |
| | | .directive('uiSref', $StateRefDirective) |
| | | .directive('uiSrefActive', $StateActiveDirective); |
| | | |
| | | /** |
| | | * @ngdoc filter |
| | | * @name ui.router.state.filter:isState |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. |
| | | */ |
| | | $IsStateFilter.$inject = ['$state']; |
| | | function $IsStateFilter($state) { |
| | | return function(state) { |
| | | return $state.is(state); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc filter |
| | | * @name ui.router.state.filter:includedByState |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * |
| | | * @description |
| | | * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. |
| | | */ |
| | | $IncludedByStateFilter.$inject = ['$state']; |
| | | function $IncludedByStateFilter($state) { |
| | | return function(state) { |
| | | return $state.includes(state); |
| | | }; |
| | | } |
| | | |
| | | angular.module('ui.router.state') |
| | | .filter('isState', $IsStateFilter) |
| | | .filter('includedByState', $IncludedByStateFilter); |
| | | |
| | | /* |
| | | * @ngdoc object |
| | | * @name ui.router.compat.$routeProvider |
| | | * |
| | | * @requires ui.router.state.$stateProvider |
| | | * @requires ui.router.router.$urlRouterProvider |
| | | * |
| | | * @description |
| | | * `$routeProvider` of the `ui.router.compat` module overwrites the existing |
| | | * `routeProvider` from the core. This is done to provide compatibility between |
| | | * the UI Router and the core router. |
| | | * |
| | | * It also provides a `when()` method to register routes that map to certain urls. |
| | | * Behind the scenes it actually delegates either to |
| | | * {@link ui.router.router.$urlRouterProvider $urlRouterProvider} or to the |
| | | * {@link ui.router.state.$stateProvider $stateProvider} to postprocess the given |
| | | * router definition object. |
| | | */ |
| | | $RouteProvider.$inject = ['$stateProvider', '$urlRouterProvider']; |
| | | function $RouteProvider( $stateProvider, $urlRouterProvider) { |
| | | |
| | | var routes = []; |
| | | |
| | | onEnterRoute.$inject = ['$$state']; |
| | | function onEnterRoute( $$state) { |
| | | /*jshint validthis: true */ |
| | | this.locals = $$state.locals.globals; |
| | | this.params = this.locals.$stateParams; |
| | | } |
| | | |
| | | function onExitRoute() { |
| | | /*jshint validthis: true */ |
| | | this.locals = null; |
| | | this.params = null; |
| | | } |
| | | |
| | | this.when = when; |
| | | /* |
| | | * @ngdoc function |
| | | * @name ui.router.compat.$routeProvider#when |
| | | * @methodOf ui.router.compat.$routeProvider |
| | | * |
| | | * @description |
| | | * Registers a route with a given route definition object. The route definition |
| | | * object has the same interface the angular core route definition object has. |
| | | * |
| | | * @example |
| | | * <pre> |
| | | * var app = angular.module('app', ['ui.router.compat']); |
| | | * |
| | | * app.config(function ($routeProvider) { |
| | | * $routeProvider.when('home', { |
| | | * controller: function () { ... }, |
| | | * templateUrl: 'path/to/template' |
| | | * }); |
| | | * }); |
| | | * </pre> |
| | | * |
| | | * @param {string} url URL as string |
| | | * @param {object} route Route definition object |
| | | * |
| | | * @return {object} $routeProvider - $routeProvider instance |
| | | */ |
| | | function when(url, route) { |
| | | /*jshint validthis: true */ |
| | | if (route.redirectTo != null) { |
| | | // Redirect, configure directly on $urlRouterProvider |
| | | var redirect = route.redirectTo, handler; |
| | | if (isString(redirect)) { |
| | | handler = redirect; // leave $urlRouterProvider to handle |
| | | } else if (isFunction(redirect)) { |
| | | // Adapt to $urlRouterProvider API |
| | | handler = function (params, $location) { |
| | | return redirect(params, $location.path(), $location.search()); |
| | | }; |
| | | } else { |
| | | throw new Error("Invalid 'redirectTo' in when()"); |
| | | } |
| | | $urlRouterProvider.when(url, handler); |
| | | } else { |
| | | // Regular route, configure as state |
| | | $stateProvider.state(inherit(route, { |
| | | parent: null, |
| | | name: 'route:' + encodeURIComponent(url), |
| | | url: url, |
| | | onEnter: onEnterRoute, |
| | | onExit: onExitRoute |
| | | })); |
| | | } |
| | | routes.push(route); |
| | | return this; |
| | | } |
| | | |
| | | /* |
| | | * @ngdoc object |
| | | * @name ui.router.compat.$route |
| | | * |
| | | * @requires ui.router.state.$state |
| | | * @requires $rootScope |
| | | * @requires $routeParams |
| | | * |
| | | * @property {object} routes - Array of registered routes. |
| | | * @property {object} params - Current route params as object. |
| | | * @property {string} current - Name of the current route. |
| | | * |
| | | * @description |
| | | * The `$route` service provides interfaces to access defined routes. It also let's |
| | | * you access route params through `$routeParams` service, so you have fully |
| | | * control over all the stuff you would actually get from angular's core `$route` |
| | | * service. |
| | | */ |
| | | this.$get = $get; |
| | | $get.$inject = ['$state', '$rootScope', '$routeParams']; |
| | | function $get( $state, $rootScope, $routeParams) { |
| | | |
| | | var $route = { |
| | | routes: routes, |
| | | params: $routeParams, |
| | | current: undefined |
| | | }; |
| | | |
| | | function stateAsRoute(state) { |
| | | return (state.name !== '') ? state : undefined; |
| | | } |
| | | |
| | | $rootScope.$on('$stateChangeStart', function (ev, to, toParams, from, fromParams) { |
| | | $rootScope.$broadcast('$routeChangeStart', stateAsRoute(to), stateAsRoute(from)); |
| | | }); |
| | | |
| | | $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) { |
| | | $route.current = stateAsRoute(to); |
| | | $rootScope.$broadcast('$routeChangeSuccess', stateAsRoute(to), stateAsRoute(from)); |
| | | copy(toParams, $route.params); |
| | | }); |
| | | |
| | | $rootScope.$on('$stateChangeError', function (ev, to, toParams, from, fromParams, error) { |
| | | $rootScope.$broadcast('$routeChangeError', stateAsRoute(to), stateAsRoute(from), error); |
| | | }); |
| | | |
| | | return $route; |
| | | } |
| | | } |
| | | |
| | | angular.module('ui.router.compat') |
| | | .provider('$route', $RouteProvider) |
| | | .directive('ngView', $ViewDirective); |
| | | })(window, window.angular); |
New file |
| | |
| | | /** |
| | | * State-based routing for AngularJS |
| | | * @version v0.2.10 |
| | | * @link http://angular-ui.github.com/ |
| | | * @license MIT License, http://www.opensource.org/licenses/MIT |
| | | */ |
| | | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return I(new(I(function(){},{prototype:a})),b)}function e(a){return H(arguments,function(b){b!==a&&H(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return I({},i,b)}function i(a,b){var c={};return H(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e<c.length;e++){var f=c[e];if(a[f]!=b[f])return!1}return!0}function k(a,b){var c={};return H(a,function(a){c[a]=b[a]}),c}function l(a,b){var d=1,f=2,g={},h=[],i=g,j=I(a.when(g),{$$promises:g,$$values:g});this.study=function(g){function k(a,c){if(o[c]!==f){if(n.push(c),o[c]===d)throw n.splice(0,n.indexOf(c)),new Error("Cyclic dependency: "+n.join(" -> "));if(o[c]=d,E(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);H(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return F(a)&&a.then&&a.$$promises}if(!F(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return H(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!C(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;H(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!F(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=I({},d),s=1+m.length/3,t=!1;if(C(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(I(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return C(a.template)?this.fromString(a.template,b):C(a.templateUrl)?this.fromUrl(a.templateUrl,b):C(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return D(a)?a(b):a},this.fromUrl=function(c,d){return D(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),H(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return F(a)&&D(a.exec)&&D(a.format)&&D(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return C(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!D(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(E(a)){var b=a;a=function(){return b}}else if(!D(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=E(f);if(E(e)&&(e=a.compile(e)),!h&&!D(f)&&!G(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),I(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:E(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),I(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(E(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=E(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=w[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){x[a]||(x[a]=[]),x[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!E(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(w.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):E(b.parent)?b.parent:"";if(e&&!w[e])return m(e,b.self);for(var f in z)D(z[f])&&(b[f]=z[f](b,z.$delegates[f]));if(w[c]=b,!b[y]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){v.$current.navigable==b&&j(a,c)||v.transitionTo(b,a,{location:!1})}]),x[c])for(var g=0;g<x[c].length;g++)n(x[c][g]);return b}function o(a){return a.indexOf("*")>-1}function p(a){var b=a.split("."),c=v.$current.name.split(".");if("**"===b[0]&&(c=c.slice(c.indexOf(b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(c.indexOf(b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function q(a,b){return E(a)&&!C(b)?z[a]:D(b)&&E(a)?(z[a]&&!z.$delegates[a]&&(z.$delegates[a]=z[a]),z[a]=b,this):this}function r(a,b){return F(a)?b=a:b.name=a,n(b),this}function s(a,e,g,m,n,q,r,s,x){function z(){r.url()!==M&&(r.url(M),r.replace())}function A(a,c,d,f,h){var i=d?c:k(a.params,c),j={$stateParams:i};h.resolve=n.resolve(a.resolve,j,h.resolve,a);var l=[h.resolve.then(function(a){h.globals=a})];return f&&l.push(f),H(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return g.load(d,{view:c,locals:j,params:i,notify:!1})||""}],l.push(n.resolve(e,j,h.resolve,a).then(function(f){if(D(c.controllerProvider)||G(c.controllerProvider)){var g=b.extend({},e,j);f.$$controller=m.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,h[d]=f}))}),e.all(l).then(function(){return h})}var B=e.reject(new Error("transition superseded")),F=e.reject(new Error("transition prevented")),K=e.reject(new Error("transition aborted")),L=e.reject(new Error("transition failed")),M=r.url(),N=x.baseHref();return u.locals={resolve:null,globals:{$stateParams:{}}},v={params:{},current:u.self,$current:u,transition:null},v.reload=function(){v.transitionTo(v.current,q,{reload:!0,inherit:!1,notify:!1})},v.go=function(a,b,c){return this.transitionTo(a,b,I({inherit:!0,relative:v.$current},c))},v.transitionTo=function(b,c,f){c=c||{},f=I({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,k=v.$current,n=v.params,o=k.path,p=l(b,f.relative);if(!C(p)){var s={to:b,toParams:c,options:f};if(g=a.$broadcast("$stateNotFound",s,k.self,n),g.defaultPrevented)return z(),K;if(g.retry){if(f.$retry)return z(),L;var w=v.transition=e.when(g.retry);return w.then(function(){return w!==v.transition?B:(s.options.$retry=!0,v.transitionTo(s.to,s.toParams,s.options))},function(){return K}),z(),w}if(b=s.to,c=s.toParams,f=s.options,p=l(b,f.relative),!C(p)){if(f.relative)throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'");throw new Error("No such state '"+b+"'")}}if(p[y])throw new Error("Cannot transition to abstract state '"+b+"'");f.inherit&&(c=h(q,c||{},v.$current,p)),b=p;var x,D,E=b.path,G=u.locals,H=[];for(x=0,D=E[x];D&&D===o[x]&&j(c,n,D.ownParams)&&!f.reload;x++,D=E[x])G=H[x]=D.locals;if(t(b,k,G,f))return b.self.reloadOnSearch!==!1&&z(),v.transition=null,e.when(v.current);if(c=i(b.params,c||{}),f.notify&&(g=a.$broadcast("$stateChangeStart",b.self,c,k.self,n),g.defaultPrevented))return z(),F;for(var N=e.when(G),O=x;O<E.length;O++,D=E[O])G=H[O]=d(G),N=A(D,c,D===b,N,G);var P=v.transition=N.then(function(){var d,e,g;if(v.transition!==P)return B;for(d=o.length-1;d>=x;d--)g=o[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=x;d<E.length;d++)e=E[d],e.locals=H[d],e.self.onEnter&&m.invoke(e.self.onEnter,e.self,e.locals.globals);if(v.transition!==P)return B;v.$current=b,v.current=b.self,v.params=c,J(v.params,q),v.transition=null;var h=b.navigable;return f.location&&h&&(r.url(h.url.format(h.locals.globals.$stateParams)),"replace"===f.location&&r.replace()),f.notify&&a.$broadcast("$stateChangeSuccess",b.self,c,k.self,n),M=r.url(),v.current},function(d){return v.transition!==P?B:(v.transition=null,a.$broadcast("$stateChangeError",b.self,c,k.self,n,d),z(),e.reject(d))});return P},v.is=function(a,d){var e=l(a);return C(e)?v.$current!==e?!1:C(d)&&null!==d?b.equals(q,d):!0:c},v.includes=function(a,d){if(E(a)&&o(a)){if(!p(a))return!1;a=v.$current.name}var e=l(a);if(!C(e))return c;if(!C(v.$current.includes[e.name]))return!1;var f=!0;return b.forEach(d,function(a,b){C(q[b])&&q[b]===a||(f=!1)}),f},v.href=function(a,b,c){c=I({lossy:!0,inherit:!1,absolute:!1,relative:v.$current},c||{});var d=l(a,c.relative);if(!C(d))return null;b=h(q,b||{},v.$current,d);var e=d&&c.lossy?d.navigable:d,g=e&&e.url?e.url.format(i(d.params,b||{})):null;return!f.html5Mode()&&g&&(g="#"+f.hashPrefix()+g),"/"!==N&&(f.html5Mode()?g=N.slice(0,-1)+g:c.absolute&&(g=N.slice(1)+g)),c.absolute&&g&&(g=r.protocol()+"://"+r.host()+(80==r.port()||443==r.port()?"":":"+r.port())+(!f.html5Mode()&&g?"/":"")+g),g},v.get=function(a,b){if(!C(a)){var c=[];return H(w,function(a){c.push(a.self)}),c}var d=l(a,b);return d&&d.self?d.self:null},v}function t(a,b,c,d){return a!==b||(c!==b.locals||d.reload)&&a.self.reloadOnSearch!==!1?void 0:!0}var u,v,w={},x={},y="abstract",z={parent:function(a){if(C(a.parent)&&a.parent)return l(a.parent);var b=/^(.+)\.[^.]+$/.exec(a.name);return b?l(b[1]):u},data:function(a){return a.parent&&a.parent.data&&(a.data=a.self.data=I({},a.parent.data,a.data)),a.data},url:function(a){var b=a.url;if(E(b))return"^"==b.charAt(0)?e.compile(b.substring(1)):(a.parent.navigable||u).url.concat(b);if(e.isMatcher(b)||null==b)return b;throw new Error("Invalid url '"+b+"' in state '"+a+"'")},navigable:function(a){return a.url?a:a.parent?a.parent.navigable:null},params:function(a){if(!a.params)return a.url?a.url.parameters():a.parent.params;if(!G(a.params))throw new Error("Invalid params in state '"+a+"'");if(a.url)throw new Error("Both params and url specicified in state '"+a+"'");return a.params},views:function(a){var b={};return H(C(a.views)?a.views:{"":a},function(c,d){d.indexOf("@")<0&&(d+="@"+a.parent.name),b[d]=c}),b},ownParams:function(a){if(!a.parent)return a.params;var b={};H(a.params,function(a){b[a]=!0}),H(a.parent.params,function(c){if(!b[c])throw new Error("Missing required parameter '"+c+"' in state '"+a.name+"'");b[c]=!1});var c=[];return H(b,function(a,b){a&&c.push(b)}),c},path:function(a){return a.parent?a.parent.path.concat(a):[]},includes:function(a){var b=a.parent?I({},a.parent.includes):{};return b[a.name]=!0,b},$delegates:{}};u=n({name:"",url:"^",views:null,"abstract":!0}),u.navigable=null,this.decorator=q,this.state=r,this.$get=s,s.$inject=["$rootScope","$q","$view","$injector","$resolve","$stateParams","$location","$urlRouter","$browser"]}function r(){function a(a,b){return{load:function(c,d){var e,f={template:null,controller:null,view:null,locals:null,notify:!0,async:!0,params:{}};return d=I(f,d),d.view&&(e=b.fromConfig(d.view,d.params,d.locals)),e&&d.notify&&a.$broadcast("$viewContentLoading",d),e}}}this.$get=a,a.$inject=["$rootScope","$templateFactory"]}function s(){var a=!1;this.useAnchorScroll=function(){a=!0},this.$get=["$anchorScroll","$timeout",function(b,c){return a?b:function(a){c(function(){a[0].scrollIntoView()},0,!1)}}]}function t(a,c,d){function e(){return c.has?function(a){return c.has(a)?c.get(a):null}:function(a){try{return c.get(a)}catch(b){return null}}}function f(a,b){var c=function(){return{enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}}};if(i)return{enter:function(a,b,c){i.enter(a,null,b,c)},leave:function(a,b){i.leave(a,b)}};if(h){var d=h&&h(b,a);return{enter:function(a,b,c){d.enter(a,null,b),c()},leave:function(a,b){d.leave(a),b()}}}return c()}var g=e(),h=g("$animator"),i=g("$animate"),j={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,e,g){return function(c,e,h){function i(){k&&(k.remove(),k=null),m&&(m.$destroy(),m=null),l&&(q.leave(l,function(){k=null}),k=l,l=null)}function j(f){var h=c.$new(),j=l&&l.data("$uiViewName"),k=j&&a.$current&&a.$current.locals[j];if(f||k!==n){var r=g(h,function(a){q.enter(a,e,function(){(b.isDefined(p)&&!p||c.$eval(p))&&d(a)}),i()});n=a.$current.locals[r.data("$uiViewName")],l=r,m=h,m.$emit("$viewContentLoaded"),m.$eval(o)}}var k,l,m,n,o=h.onload||"",p=h.autoscroll,q=f(h,c);c.$on("$stateChangeSuccess",function(){j(!1)}),c.$on("$viewContentLoading",function(){j(!1)}),j(!0)}}};return j}function u(a,b,c){return{restrict:"ECA",priority:-400,compile:function(d){var e=d.html();return function(d,f,g){var h=g.uiView||g.name||"",i=f.inheritedData("$uiView");h.indexOf("@")<0&&(h=h+"@"+(i?i.state.name:"")),f.data("$uiViewName",h);var j=c.$current,k=j&&j.locals[h];if(k){f.data("$uiView",{name:h,state:k.$$state}),f.html(k.$template?k.$template:e);var l=a(f.contents());if(k.$$controller){k.$scope=d;var m=b(k.$$controller,k);k.$$controllerAs&&(d[k.$$controllerAs]=m),f.data("$ngControllerController",m),f.children().data("$ngControllerController",m)}l(d)}}}}}function v(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function w(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function x(a,c){var d=["location","inherit","reload"];return{restrict:"A",require:"?^uiSrefActive",link:function(e,f,g,h){var i=v(g.uiSref),j=null,k=w(f)||a.$current,l="FORM"===f[0].nodeName,m=l?"action":"href",n=!0,o={relative:k},p=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in p&&(o[a]=p[a])});var q=function(b){if(b&&(j=b),n){var c=a.href(i.state,j,o);return h&&h.$$setStateInfo(i.state,j),c?void(f[0][m]=c):(n=!1,!1)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a){a!==j&&q(a)},!0),j=e.$eval(i.paramExpr)),q(),l||f.bind("click",function(b){var d=b.which||b.button;d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target")||(c(function(){a.go(i.state,j,o)}),b.preventDefault())})}}}function y(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,w(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}]}}function z(a){return function(b){return a.is(b)}}function A(a){return function(b){return a.includes(b)}}function B(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(E(j))h=j;else{if(!D(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),J(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var C=b.isDefined,D=b.isFunction,E=b.isString,F=b.isObject,G=b.isArray,H=b.forEach,I=b.extend,J=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),b.module("ui.router.state").provider("$uiViewScroll",s),t.$inject=["$state","$injector","$uiViewScroll"],u.$inject=["$compile","$controller","$state"],b.module("ui.router.state").directive("uiView",t),b.module("ui.router.state").directive("uiView",u),x.$inject=["$state","$timeout"],y.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",x).directive("uiSrefActive",y),z.$inject=["$state"],A.$inject=["$state"],b.module("ui.router.state").filter("isState",z).filter("includedByState",A),B.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",B).directive("ngView",t)}(window,window.angular); |
New file |
| | |
| | | /*! |
| | | angular-xeditable - 0.1.8 |
| | | Edit-in-place for angular.js |
| | | Build date: 2014-01-10 |
| | | */ |
| | | /** |
| | | * Angular-xeditable module |
| | | * |
| | | */ |
| | | angular.module('xeditable', []) |
| | | |
| | | |
| | | /** |
| | | * Default options. |
| | | * |
| | | * @namespace editable-options |
| | | */ |
| | | //todo: maybe better have editableDefaults, not options... |
| | | .value('editableOptions', { |
| | | /** |
| | | * Theme. Possible values `bs3`, `bs2`, `default`. |
| | | * |
| | | * @var {string} theme |
| | | * @memberOf editable-options |
| | | */ |
| | | theme: 'default', |
| | | /** |
| | | * Whether to show buttons for single editalbe element. |
| | | * Possible values `right` (default), `no`. |
| | | * |
| | | * @var {string} buttons |
| | | * @memberOf editable-options |
| | | */ |
| | | buttons: 'right', |
| | | /** |
| | | * Default value for `blur` attribute of single editable element. |
| | | * Can be `cancel|submit|ignore`. |
| | | * |
| | | * @var {string} blurElem |
| | | * @memberOf editable-options |
| | | */ |
| | | blurElem: 'cancel', |
| | | /** |
| | | * Default value for `blur` attribute of editable form. |
| | | * Can be `cancel|submit|ignore`. |
| | | * |
| | | * @var {string} blurForm |
| | | * @memberOf editable-options |
| | | */ |
| | | blurForm: 'ignore', |
| | | /** |
| | | * How input elements get activated. Possible values: `focus|select|none`. |
| | | * |
| | | * @var {string} activate |
| | | * @memberOf editable-options |
| | | */ |
| | | activate: 'focus' |
| | | |
| | | }); |
| | | /* |
| | | Angular-ui bootstrap datepicker |
| | | http://angular-ui.github.io/bootstrap/#/datepicker |
| | | */ |
| | | angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableBsdate', |
| | | inputTpl: '<input type="text">' |
| | | }); |
| | | }]); |
| | | /* |
| | | Angular-ui bootstrap editable timepicker |
| | | http://angular-ui.github.io/bootstrap/#/timepicker |
| | | */ |
| | | angular.module('xeditable').directive('editableBstime', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableBstime', |
| | | inputTpl: '<timepicker></timepicker>', |
| | | render: function() { |
| | | this.parent.render.call(this); |
| | | |
| | | // timepicker can't update model when ng-model set directly to it |
| | | // see: https://github.com/angular-ui/bootstrap/issues/1141 |
| | | // so we wrap it into DIV |
| | | var div = angular.element('<div class="well well-small" style="display:inline-block;"></div>'); |
| | | |
| | | // move ng-model to wrapping div |
| | | div.attr('ng-model', this.inputEl.attr('ng-model')); |
| | | this.inputEl.removeAttr('ng-model'); |
| | | |
| | | // move ng-change to wrapping div |
| | | if(this.attrs.eNgChange) { |
| | | div.attr('ng-change', this.inputEl.attr('ng-change')); |
| | | this.inputEl.removeAttr('ng-change'); |
| | | } |
| | | |
| | | // wrap |
| | | this.inputEl.wrap(div); |
| | | } |
| | | }); |
| | | }]); |
| | | //checkbox |
| | | angular.module('xeditable').directive('editableCheckbox', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableCheckbox', |
| | | inputTpl: '<input type="checkbox">', |
| | | render: function() { |
| | | this.parent.render.call(this); |
| | | if(this.attrs.eTitle) { |
| | | this.inputEl.wrap('<label></label>'); |
| | | this.inputEl.after(angular.element('<span></span>').text(this.attrs.eTitle)); |
| | | } |
| | | }, |
| | | autosubmit: function() { |
| | | var self = this; |
| | | self.inputEl.bind('change', function() { |
| | | setTimeout(function() { |
| | | self.scope.$apply(function() { |
| | | self.scope.$form.$submit(); |
| | | }); |
| | | }, 500); |
| | | }); |
| | | } |
| | | }); |
| | | }]); |
| | | // checklist |
| | | angular.module('xeditable').directive('editableChecklist', [ |
| | | 'editableDirectiveFactory', |
| | | 'editableNgOptionsParser', |
| | | function(editableDirectiveFactory, editableNgOptionsParser) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableChecklist', |
| | | inputTpl: '<span></span>', |
| | | useCopy: true, |
| | | render: function() { |
| | | this.parent.render.call(this); |
| | | var parsed = editableNgOptionsParser(this.attrs.eNgOptions); |
| | | var html = '<label ng-repeat="'+parsed.ngRepeat+'">'+ |
| | | '<input type="checkbox" checklist-model="$parent.$data" checklist-value="'+parsed.locals.valueFn+'">'+ |
| | | '<span ng-bind="'+parsed.locals.displayFn+'"></span></label>'; |
| | | |
| | | this.inputEl.removeAttr('ng-model'); |
| | | this.inputEl.removeAttr('ng-options'); |
| | | this.inputEl.html(html); |
| | | } |
| | | }); |
| | | }]); |
| | | /* |
| | | Input types: text|email|tel|number|url|search|color|date|datetime|time|month|week |
| | | */ |
| | | |
| | | (function() { |
| | | |
| | | var types = 'text|email|tel|number|url|search|color|date|datetime|time|month|week'.split('|'); |
| | | |
| | | //todo: datalist |
| | | |
| | | // generate directives |
| | | angular.forEach(types, function(type) { |
| | | var directiveName = 'editable'+type.charAt(0).toUpperCase() + type.slice(1); |
| | | angular.module('xeditable').directive(directiveName, ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: directiveName, |
| | | inputTpl: '<input type="'+type+'">' |
| | | }); |
| | | }]); |
| | | }); |
| | | |
| | | //`range` is bit specific |
| | | angular.module('xeditable').directive('editableRange', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableRange', |
| | | inputTpl: '<input type="range" id="range" name="range">', |
| | | render: function() { |
| | | this.parent.render.call(this); |
| | | this.inputEl.after('<output>{{$data}}</output>'); |
| | | } |
| | | }); |
| | | }]); |
| | | |
| | | }()); |
| | | |
| | | |
| | | // radiolist |
| | | angular.module('xeditable').directive('editableRadiolist', [ |
| | | 'editableDirectiveFactory', |
| | | 'editableNgOptionsParser', |
| | | function(editableDirectiveFactory, editableNgOptionsParser) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableRadiolist', |
| | | inputTpl: '<span></span>', |
| | | render: function() { |
| | | this.parent.render.call(this); |
| | | var parsed = editableNgOptionsParser(this.attrs.eNgOptions); |
| | | var html = '<label ng-repeat="'+parsed.ngRepeat+'">'+ |
| | | '<input type="radio" ng-model="$parent.$data" value="{{'+parsed.locals.valueFn+'}}">'+ |
| | | '<span ng-bind="'+parsed.locals.displayFn+'"></span></label>'; |
| | | |
| | | this.inputEl.removeAttr('ng-model'); |
| | | this.inputEl.removeAttr('ng-options'); |
| | | this.inputEl.html(html); |
| | | }, |
| | | autosubmit: function() { |
| | | var self = this; |
| | | self.inputEl.bind('change', function() { |
| | | setTimeout(function() { |
| | | self.scope.$apply(function() { |
| | | self.scope.$form.$submit(); |
| | | }); |
| | | }, 500); |
| | | }); |
| | | } |
| | | }); |
| | | }]); |
| | | //select |
| | | angular.module('xeditable').directive('editableSelect', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableSelect', |
| | | inputTpl: '<select></select>', |
| | | autosubmit: function() { |
| | | var self = this; |
| | | self.inputEl.bind('change', function() { |
| | | self.scope.$apply(function() { |
| | | self.scope.$form.$submit(); |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | }]); |
| | | //textarea |
| | | angular.module('xeditable').directive('editableTextarea', ['editableDirectiveFactory', |
| | | function(editableDirectiveFactory) { |
| | | return editableDirectiveFactory({ |
| | | directiveName: 'editableTextarea', |
| | | inputTpl: '<textarea></textarea>', |
| | | addListeners: function() { |
| | | var self = this; |
| | | self.parent.addListeners.call(self); |
| | | // submit textarea by ctrl+enter even with buttons |
| | | if (self.single && self.buttons !== 'no') { |
| | | self.autosubmit(); |
| | | } |
| | | }, |
| | | autosubmit: function() { |
| | | var self = this; |
| | | self.inputEl.bind('keydown', function(e) { |
| | | if ((e.ctrlKey || e.metaKey) && (e.keyCode === 13)) { |
| | | self.scope.$apply(function() { |
| | | self.scope.$form.$submit(); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }]); |
| | | |
| | | /** |
| | | * EditableController class. |
| | | * Attached to element with `editable-xxx` directive. |
| | | * |
| | | * @namespace editable-element |
| | | */ |
| | | /* |
| | | TODO: this file should be refactored to work more clear without closures! |
| | | */ |
| | | angular.module('xeditable').factory('editableController', |
| | | ['$q', 'editableUtils', |
| | | function($q, editableUtils) { |
| | | |
| | | //EditableController function |
| | | EditableController.$inject = ['$scope', '$attrs', '$element', '$parse', 'editableThemes', 'editableOptions', '$rootScope', '$compile', '$q']; |
| | | function EditableController($scope, $attrs, $element, $parse, editableThemes, editableOptions, $rootScope, $compile, $q) { |
| | | var valueGetter; |
| | | |
| | | //if control is disabled - it does not participate in waiting process |
| | | var inWaiting; |
| | | |
| | | var self = this; |
| | | |
| | | self.scope = $scope; |
| | | self.elem = $element; |
| | | self.attrs = $attrs; |
| | | self.inputEl = null; |
| | | self.editorEl = null; |
| | | self.single = true; |
| | | self.error = ''; |
| | | self.theme = editableThemes[editableOptions.theme] || editableThemes['default']; |
| | | self.parent = {}; |
| | | |
| | | //to be overwritten by directive |
| | | self.inputTpl = ''; |
| | | self.directiveName = ''; |
| | | |
| | | // with majority of controls copy is not needed, but.. |
| | | // copy MUST NOT be used for `select-multiple` with objects as items |
| | | // copy MUST be used for `checklist` |
| | | self.useCopy = false; |
| | | |
| | | //runtime (defaults) |
| | | self.single = null; |
| | | |
| | | /** |
| | | * Attributes defined with `e-*` prefix automatically transfered from original element to |
| | | * control. |
| | | * For example, if you set `<span editable-text="user.name" e-style="width: 100px"`> |
| | | * then input will appear as `<input style="width: 100px">`. |
| | | * See [demo](#text-customize). |
| | | * |
| | | * @var {any|attribute} e-* |
| | | * @memberOf editable-element |
| | | */ |
| | | |
| | | /** |
| | | * Whether to show ok/cancel buttons. Values: `right|no`. |
| | | * If set to `no` control automatically submitted when value changed. |
| | | * If control is part of form buttons will never be shown. |
| | | * |
| | | * @var {string|attribute} buttons |
| | | * @memberOf editable-element |
| | | */ |
| | | self.buttons = 'right'; |
| | | /** |
| | | * Action when control losses focus. Values: `cancel|submit|ignore`. |
| | | * Has sense only for single editable element. |
| | | * Otherwise, if control is part of form - you should set `blur` of form, not of individual element. |
| | | * |
| | | * @var {string|attribute} blur |
| | | * @memberOf editable-element |
| | | */ |
| | | // no real `blur` property as it is transfered to editable form |
| | | |
| | | //init |
| | | self.init = function(single) { |
| | | self.single = single; |
| | | |
| | | self.name = $attrs.eName || $attrs[self.directiveName]; |
| | | /* |
| | | if(!$attrs[directiveName] && !$attrs.eNgModel && ($attrs.eValue === undefined)) { |
| | | throw 'You should provide value for `'+directiveName+'` or `e-value` in editable element!'; |
| | | } |
| | | */ |
| | | if($attrs[self.directiveName]) { |
| | | valueGetter = $parse($attrs[self.directiveName]); |
| | | } else { |
| | | throw 'You should provide value for `'+self.directiveName+'` in editable element!'; |
| | | } |
| | | |
| | | // settings for single and non-single |
| | | if (!self.single) { |
| | | // hide buttons for non-single |
| | | self.buttons = 'no'; |
| | | } else { |
| | | self.buttons = self.attrs.buttons || editableOptions.buttons; |
| | | } |
| | | |
| | | //if name defined --> watch changes and update $data in form |
| | | if($attrs.eName) { |
| | | self.scope.$watch('$data', function(newVal){ |
| | | self.scope.$form.$data[$attrs.eName] = newVal; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * Called when control is shown. |
| | | * See [demo](#select-remote). |
| | | * |
| | | * @var {method|attribute} onshow |
| | | * @memberOf editable-element |
| | | */ |
| | | if($attrs.onshow) { |
| | | self.onshow = function() { |
| | | return self.catchError($parse($attrs.onshow)($scope)); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Called when control is hidden after both save or cancel. |
| | | * |
| | | * @var {method|attribute} onhide |
| | | * @memberOf editable-element |
| | | */ |
| | | if($attrs.onhide) { |
| | | self.onhide = function() { |
| | | return $parse($attrs.onhide)($scope); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Called when control is cancelled. |
| | | * |
| | | * @var {method|attribute} oncancel |
| | | * @memberOf editable-element |
| | | */ |
| | | if($attrs.oncancel) { |
| | | self.oncancel = function() { |
| | | return $parse($attrs.oncancel)($scope); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Called during submit before value is saved to model. |
| | | * See [demo](#onbeforesave). |
| | | * |
| | | * @var {method|attribute} onbeforesave |
| | | * @memberOf editable-element |
| | | */ |
| | | if ($attrs.onbeforesave) { |
| | | self.onbeforesave = function() { |
| | | return self.catchError($parse($attrs.onbeforesave)($scope)); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Called during submit after value is saved to model. |
| | | * See [demo](#onaftersave). |
| | | * |
| | | * @var {method|attribute} onaftersave |
| | | * @memberOf editable-element |
| | | */ |
| | | if ($attrs.onaftersave) { |
| | | self.onaftersave = function() { |
| | | return self.catchError($parse($attrs.onaftersave)($scope)); |
| | | }; |
| | | } |
| | | |
| | | // watch change of model to update editable element |
| | | // now only add/remove `editable-empty` class. |
| | | // Initially this method called with newVal = undefined, oldVal = undefined |
| | | // so no need initially call handleEmpty() explicitly |
| | | $scope.$parent.$watch($attrs[self.directiveName], function(newVal, oldVal) { |
| | | self.handleEmpty(); |
| | | }); |
| | | }; |
| | | |
| | | self.render = function() { |
| | | var theme = self.theme; |
| | | |
| | | //build input |
| | | self.inputEl = angular.element(self.inputTpl); |
| | | |
| | | //build controls |
| | | self.controlsEl = angular.element(theme.controlsTpl); |
| | | self.controlsEl.append(self.inputEl); |
| | | |
| | | //build buttons |
| | | if(self.buttons !== 'no') { |
| | | self.buttonsEl = angular.element(theme.buttonsTpl); |
| | | self.submitEl = angular.element(theme.submitTpl); |
| | | self.cancelEl = angular.element(theme.cancelTpl); |
| | | self.buttonsEl.append(self.submitEl).append(self.cancelEl); |
| | | self.controlsEl.append(self.buttonsEl); |
| | | |
| | | self.inputEl.addClass('editable-has-buttons'); |
| | | } |
| | | |
| | | //build error |
| | | self.errorEl = angular.element(theme.errorTpl); |
| | | self.controlsEl.append(self.errorEl); |
| | | |
| | | //build editor |
| | | self.editorEl = angular.element(self.single ? theme.formTpl : theme.noformTpl); |
| | | self.editorEl.append(self.controlsEl); |
| | | |
| | | // transfer `e-*|data-e-*|x-e-*` attributes |
| | | for(var k in $attrs.$attr) { |
| | | if(k.length <= 1) { |
| | | continue; |
| | | } |
| | | var transferAttr = false; |
| | | var nextLetter = k.substring(1, 2); |
| | | |
| | | // if starts with `e` + uppercase letter |
| | | if(k.substring(0, 1) === 'e' && nextLetter === nextLetter.toUpperCase()) { |
| | | transferAttr = k.substring(1); // cut `e` |
| | | } else { |
| | | continue; |
| | | } |
| | | |
| | | // exclude `form` and `ng-submit`, |
| | | if(transferAttr === 'Form' || transferAttr === 'NgSubmit') { |
| | | continue; |
| | | } |
| | | |
| | | // convert back to lowercase style |
| | | transferAttr = transferAttr.substring(0, 1).toLowerCase() + editableUtils.camelToDash(transferAttr.substring(1)); |
| | | |
| | | // workaround for attributes without value (e.g. `multiple = "multiple"`) |
| | | var attrValue = ($attrs[k] === '') ? transferAttr : $attrs[k]; |
| | | |
| | | // set attributes to input |
| | | self.inputEl.attr(transferAttr, attrValue); |
| | | } |
| | | |
| | | self.inputEl.addClass('editable-input'); |
| | | self.inputEl.attr('ng-model', '$data'); |
| | | |
| | | // add directiveName class to editor, e.g. `editable-text` |
| | | self.editorEl.addClass(editableUtils.camelToDash(self.directiveName)); |
| | | |
| | | if(self.single) { |
| | | self.editorEl.attr('editable-form', '$form'); |
| | | // transfer `blur` to form |
| | | self.editorEl.attr('blur', self.attrs.blur || (self.buttons === 'no' ? 'cancel' : editableOptions.blurElem)); |
| | | } |
| | | |
| | | //apply `postrender` method of theme |
| | | if(angular.isFunction(theme.postrender)) { |
| | | theme.postrender.call(self); |
| | | } |
| | | |
| | | }; |
| | | |
| | | // with majority of controls copy is not needed, but.. |
| | | // copy MUST NOT be used for `select-multiple` with objects as items |
| | | // copy MUST be used for `checklist` |
| | | self.setLocalValue = function() { |
| | | self.scope.$data = self.useCopy ? |
| | | angular.copy(valueGetter($scope.$parent)) : |
| | | valueGetter($scope.$parent); |
| | | }; |
| | | |
| | | //show |
| | | self.show = function() { |
| | | // set value of scope.$data |
| | | self.setLocalValue(); |
| | | |
| | | /* |
| | | Originally render() was inside init() method, but some directives polluting editorEl, |
| | | so it is broken on second openning. |
| | | Cloning is not a solution as jqLite can not clone with event handler's. |
| | | */ |
| | | self.render(); |
| | | |
| | | // insert into DOM |
| | | $element.after(self.editorEl); |
| | | |
| | | // compile (needed to attach ng-* events from markup) |
| | | $compile(self.editorEl)($scope); |
| | | |
| | | // attach listeners (`escape`, autosubmit, etc) |
| | | self.addListeners(); |
| | | |
| | | // hide element |
| | | $element.addClass('editable-hide'); |
| | | |
| | | // onshow |
| | | return self.onshow(); |
| | | }; |
| | | |
| | | //hide |
| | | self.hide = function() { |
| | | self.editorEl.remove(); |
| | | $element.removeClass('editable-hide'); |
| | | |
| | | // onhide |
| | | return self.onhide(); |
| | | }; |
| | | |
| | | // cancel |
| | | self.cancel = function() { |
| | | // oncancel |
| | | self.oncancel(); |
| | | // don't call hide() here as it called in form's code |
| | | }; |
| | | |
| | | /* |
| | | Called after show to attach listeners |
| | | */ |
| | | self.addListeners = function() { |
| | | // bind keyup for `escape` |
| | | self.inputEl.bind('keyup', function(e) { |
| | | if(!self.single) { |
| | | return; |
| | | } |
| | | |
| | | // todo: move this to editable-form! |
| | | switch(e.keyCode) { |
| | | // hide on `escape` press |
| | | case 27: |
| | | self.scope.$apply(function() { |
| | | self.scope.$form.$cancel(); |
| | | }); |
| | | break; |
| | | } |
| | | }); |
| | | |
| | | // autosubmit when `no buttons` |
| | | if (self.single && self.buttons === 'no') { |
| | | self.autosubmit(); |
| | | } |
| | | |
| | | // click - mark element as clicked to exclude in document click handler |
| | | self.editorEl.bind('click', function(e) { |
| | | // ignore right/middle button click |
| | | if (e.which !== 1) { |
| | | return; |
| | | } |
| | | |
| | | if (self.scope.$form.$visible) { |
| | | self.scope.$form._clicked = true; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // setWaiting |
| | | self.setWaiting = function(value) { |
| | | if (value) { |
| | | // participate in waiting only if not disabled |
| | | inWaiting = !self.inputEl.attr('disabled') && |
| | | !self.inputEl.attr('ng-disabled') && |
| | | !self.inputEl.attr('ng-enabled'); |
| | | if (inWaiting) { |
| | | self.inputEl.attr('disabled', 'disabled'); |
| | | if(self.buttonsEl) { |
| | | self.buttonsEl.find('button').attr('disabled', 'disabled'); |
| | | } |
| | | } |
| | | } else { |
| | | if (inWaiting) { |
| | | self.inputEl.removeAttr('disabled'); |
| | | if (self.buttonsEl) { |
| | | self.buttonsEl.find('button').removeAttr('disabled'); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | self.activate = function() { |
| | | setTimeout(function() { |
| | | var el = self.inputEl[0]; |
| | | if (editableOptions.activate === 'focus' && el.focus) { |
| | | el.focus(); |
| | | } |
| | | if (editableOptions.activate === 'select' && el.select) { |
| | | el.select(); |
| | | } |
| | | }, 0); |
| | | }; |
| | | |
| | | self.setError = function(msg) { |
| | | if(!angular.isObject(msg)) { |
| | | $scope.$error = msg; |
| | | self.error = msg; |
| | | } |
| | | }; |
| | | |
| | | /* |
| | | Checks that result is string or promise returned string and shows it as error message |
| | | Applied to onshow, onbeforesave, onaftersave |
| | | */ |
| | | self.catchError = function(result, noPromise) { |
| | | if (angular.isObject(result) && noPromise !== true) { |
| | | $q.when(result).then( |
| | | //success and fail handlers are equal |
| | | angular.bind(this, function(r) { |
| | | this.catchError(r, true); |
| | | }), |
| | | angular.bind(this, function(r) { |
| | | this.catchError(r, true); |
| | | }) |
| | | ); |
| | | //check $http error |
| | | } else if (noPromise && angular.isObject(result) && result.status && |
| | | (result.status !== 200) && result.data && angular.isString(result.data)) { |
| | | this.setError(result.data); |
| | | //set result to string: to let form know that there was error |
| | | result = result.data; |
| | | } else if (angular.isString(result)) { |
| | | this.setError(result); |
| | | } |
| | | return result; |
| | | }; |
| | | |
| | | self.save = function() { |
| | | valueGetter.assign($scope.$parent, angular.copy(self.scope.$data)); |
| | | |
| | | // no need to call handleEmpty here as we are watching change of model value |
| | | // self.handleEmpty(); |
| | | }; |
| | | |
| | | /* |
| | | attach/detach `editable-empty` class to element |
| | | */ |
| | | self.handleEmpty = function() { |
| | | var val = valueGetter($scope.$parent); |
| | | var isEmpty = val === null || val === undefined || val === "" || (angular.isArray(val) && val.length === 0); |
| | | $element.toggleClass('editable-empty', isEmpty); |
| | | }; |
| | | |
| | | /* |
| | | Called when `buttons = "no"` to submit automatically |
| | | */ |
| | | self.autosubmit = angular.noop; |
| | | |
| | | self.onshow = angular.noop; |
| | | self.onhide = angular.noop; |
| | | self.oncancel = angular.noop; |
| | | self.onbeforesave = angular.noop; |
| | | self.onaftersave = angular.noop; |
| | | } |
| | | |
| | | return EditableController; |
| | | }]); |
| | | |
| | | /* |
| | | editableFactory is used to generate editable directives (see `/directives` folder) |
| | | Inside it does several things: |
| | | - detect form for editable element. Form may be one of three types: |
| | | 1. autogenerated form (for single editable elements) |
| | | 2. wrapper form (element wrapped by <form> tag) |
| | | 3. linked form (element has `e-form` attribute pointing to existing form) |
| | | |
| | | - attach editableController to element |
| | | |
| | | Depends on: editableController, editableFormFactory |
| | | */ |
| | | angular.module('xeditable').factory('editableDirectiveFactory', |
| | | ['$parse', '$compile', 'editableThemes', '$rootScope', '$document', 'editableController', 'editableFormController', |
| | | function($parse, $compile, editableThemes, $rootScope, $document, editableController, editableFormController) { |
| | | |
| | | //directive object |
| | | return function(overwrites) { |
| | | return { |
| | | restrict: 'A', |
| | | scope: true, |
| | | require: [overwrites.directiveName, '?^form'], |
| | | controller: editableController, |
| | | link: function(scope, elem, attrs, ctrl) { |
| | | // editable controller |
| | | var eCtrl = ctrl[0]; |
| | | |
| | | // form controller |
| | | var eFormCtrl; |
| | | |
| | | // this variable indicates is element is bound to some existing form, |
| | | // or it's single element who's form will be generated automatically |
| | | // By default consider single element without any linked form.ß |
| | | var hasForm = false; |
| | | |
| | | // element wrapped by form |
| | | if(ctrl[1]) { |
| | | eFormCtrl = ctrl[1]; |
| | | hasForm = true; |
| | | } else if(attrs.eForm) { // element not wrapped by <form>, but we hane `e-form` attr |
| | | var getter = $parse(attrs.eForm)(scope); |
| | | if(getter) { // form exists in scope (above), e.g. editable column |
| | | eFormCtrl = getter; |
| | | hasForm = true; |
| | | } else { // form exists below or not exist at all: check document.forms |
| | | for(var i=0; i<$document[0].forms.length;i++){ |
| | | if($document[0].forms[i].name === attrs.eForm) { |
| | | // form is below and not processed yet |
| | | eFormCtrl = null; |
| | | hasForm = true; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* |
| | | if(hasForm && !attrs.eName) { |
| | | throw 'You should provide `e-name` for editable element inside form!'; |
| | | } |
| | | */ |
| | | |
| | | //check for `editable-form` attr in form |
| | | /* |
| | | if(eFormCtrl && ) { |
| | | throw 'You should provide `e-name` for editable element inside form!'; |
| | | } |
| | | */ |
| | | |
| | | // store original props to `parent` before merge |
| | | angular.forEach(overwrites, function(v, k) { |
| | | if(eCtrl[k] !== undefined) { |
| | | eCtrl.parent[k] = eCtrl[k]; |
| | | } |
| | | }); |
| | | |
| | | // merge overwrites to base editable controller |
| | | angular.extend(eCtrl, overwrites); |
| | | |
| | | // init editable ctrl |
| | | eCtrl.init(!hasForm); |
| | | |
| | | // publich editable controller as `$editable` to be referenced in html |
| | | scope.$editable = eCtrl; |
| | | |
| | | // add `editable` class to element |
| | | elem.addClass('editable'); |
| | | |
| | | // hasForm |
| | | if(hasForm) { |
| | | if(eFormCtrl) { |
| | | scope.$form = eFormCtrl; |
| | | if(!scope.$form.$addEditable) { |
| | | throw 'Form with editable elements should have `editable-form` attribute.'; |
| | | } |
| | | scope.$form.$addEditable(eCtrl); |
| | | } else { |
| | | // future form (below): add editable controller to buffer and add to form later |
| | | $rootScope.$$editableBuffer = $rootScope.$$editableBuffer || {}; |
| | | $rootScope.$$editableBuffer[attrs.eForm] = $rootScope.$$editableBuffer[attrs.eForm] || []; |
| | | $rootScope.$$editableBuffer[attrs.eForm].push(eCtrl); |
| | | scope.$form = null; //will be re-assigned later |
| | | } |
| | | // !hasForm |
| | | } else { |
| | | // create editableform controller |
| | | scope.$form = editableFormController(); |
| | | // add self to editable controller |
| | | scope.$form.$addEditable(eCtrl); |
| | | |
| | | // if `e-form` provided, publish local $form in scope |
| | | if(attrs.eForm) { |
| | | scope.$parent[attrs.eForm] = scope.$form; |
| | | } |
| | | |
| | | // bind click - if no external form defined |
| | | if(!attrs.eForm) { |
| | | elem.addClass('editable-click'); |
| | | elem.bind('click', function(e) { |
| | | e.preventDefault(); |
| | | e.editable = eCtrl; |
| | | scope.$apply(function(){ |
| | | scope.$form.$show(); |
| | | }); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | } |
| | | }; |
| | | }; |
| | | }]); |
| | | |
| | | /* |
| | | Returns editableForm controller |
| | | */ |
| | | angular.module('xeditable').factory('editableFormController', |
| | | ['$parse', '$document', '$rootScope', 'editablePromiseCollection', 'editableUtils', |
| | | function($parse, $document, $rootScope, editablePromiseCollection, editableUtils) { |
| | | |
| | | // array of opened editable forms |
| | | var shown = []; |
| | | |
| | | // bind click to body: cancel|submit|ignore forms |
| | | $document.bind('click', function(e) { |
| | | // ignore right/middle button click |
| | | if (e.which !== 1) { |
| | | return; |
| | | } |
| | | |
| | | var toCancel = []; |
| | | var toSubmit = []; |
| | | for (var i=0; i<shown.length; i++) { |
| | | |
| | | // exclude clicked |
| | | if (shown[i]._clicked) { |
| | | shown[i]._clicked = false; |
| | | continue; |
| | | } |
| | | |
| | | // exclude waiting |
| | | if (shown[i].$waiting) { |
| | | continue; |
| | | } |
| | | |
| | | if (shown[i]._blur === 'cancel') { |
| | | toCancel.push(shown[i]); |
| | | } |
| | | |
| | | if (shown[i]._blur === 'submit') { |
| | | toSubmit.push(shown[i]); |
| | | } |
| | | } |
| | | |
| | | if (toCancel.length || toSubmit.length) { |
| | | $rootScope.$apply(function() { |
| | | angular.forEach(toCancel, function(v){ v.$cancel(); }); |
| | | angular.forEach(toSubmit, function(v){ v.$submit(); }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | |
| | | var base = { |
| | | $addEditable: function(editable) { |
| | | //console.log('add editable', editable.elem, editable.elem.bind); |
| | | this.$editables.push(editable); |
| | | |
| | | //'on' is not supported in angular 1.0.8 |
| | | editable.elem.bind('$destroy', angular.bind(this, this.$removeEditable, editable)); |
| | | |
| | | //bind editable's local $form to self (if not bound yet, below form) |
| | | if (!editable.scope.$form) { |
| | | editable.scope.$form = this; |
| | | } |
| | | |
| | | //if form already shown - call show() of new editable |
| | | if (this.$visible) { |
| | | editable.catchError(editable.show()); |
| | | } |
| | | }, |
| | | |
| | | $removeEditable: function(editable) { |
| | | //arrayRemove |
| | | for(var i=0; i < this.$editables.length; i++) { |
| | | if(this.$editables[i] === editable) { |
| | | this.$editables.splice(i, 1); |
| | | return; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * Shows form with editable controls. |
| | | * |
| | | * @method $show() |
| | | * @memberOf editable-form |
| | | */ |
| | | $show: function() { |
| | | if (this.$visible) { |
| | | return; |
| | | } |
| | | |
| | | this.$visible = true; |
| | | |
| | | var pc = editablePromiseCollection(); |
| | | |
| | | //own show |
| | | pc.when(this.$onshow()); |
| | | |
| | | //clear errors |
| | | this.$setError(null, ''); |
| | | |
| | | //children show |
| | | angular.forEach(this.$editables, function(editable) { |
| | | pc.when(editable.show()); |
| | | }); |
| | | |
| | | //wait promises and activate |
| | | pc.then({ |
| | | onWait: angular.bind(this, this.$setWaiting), |
| | | onTrue: angular.bind(this, this.$activate), |
| | | onFalse: angular.bind(this, this.$activate), |
| | | onString: angular.bind(this, this.$activate) |
| | | }); |
| | | |
| | | // add to internal list of shown forms |
| | | // setTimeout needed to prevent closing right after opening (e.g. when trigger by button) |
| | | setTimeout(angular.bind(this, function() { |
| | | // clear `clicked` to get ready for clicks on visible form |
| | | this._clicked = false; |
| | | if(editableUtils.indexOf(shown, this) === -1) { |
| | | shown.push(this); |
| | | } |
| | | }), 0); |
| | | }, |
| | | |
| | | /** |
| | | * Sets focus on form field specified by `name`. |
| | | * |
| | | * @method $activate(name) |
| | | * @param {string} name name of field |
| | | * @memberOf editable-form |
| | | */ |
| | | $activate: function(name) { |
| | | var i; |
| | | if (this.$editables.length) { |
| | | //activate by name |
| | | if (angular.isString(name)) { |
| | | for(i=0; i<this.$editables.length; i++) { |
| | | if (this.$editables[i].name === name) { |
| | | this.$editables[i].activate(); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | //try activate error field |
| | | for(i=0; i<this.$editables.length; i++) { |
| | | if (this.$editables[i].error) { |
| | | this.$editables[i].activate(); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | //by default activate first field |
| | | this.$editables[0].activate(); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * Hides form with editable controls without saving. |
| | | * |
| | | * @method $hide() |
| | | * @memberOf editable-form |
| | | */ |
| | | $hide: function() { |
| | | if (!this.$visible) { |
| | | return; |
| | | } |
| | | this.$visible = false; |
| | | // self hide |
| | | this.$onhide(); |
| | | // children's hide |
| | | angular.forEach(this.$editables, function(editable) { |
| | | editable.hide(); |
| | | }); |
| | | |
| | | // remove from internal list of shown forms |
| | | editableUtils.arrayRemove(shown, this); |
| | | }, |
| | | |
| | | /** |
| | | * Triggers `oncancel` event and calls `$hide()`. |
| | | * |
| | | * @method $cancel() |
| | | * @memberOf editable-form |
| | | */ |
| | | $cancel: function() { |
| | | if (!this.$visible) { |
| | | return; |
| | | } |
| | | // self cancel |
| | | this.$oncancel(); |
| | | // children's cancel |
| | | angular.forEach(this.$editables, function(editable) { |
| | | editable.cancel(); |
| | | }); |
| | | // self hide |
| | | this.$hide(); |
| | | }, |
| | | |
| | | $setWaiting: function(value) { |
| | | this.$waiting = !!value; |
| | | // we can't just set $waiting variable and use it via ng-disabled in children |
| | | // because in editable-row form is not accessible |
| | | angular.forEach(this.$editables, function(editable) { |
| | | editable.setWaiting(!!value); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * Shows error message for particular field. |
| | | * |
| | | * @method $setError(name, msg) |
| | | * @param {string} name name of field |
| | | * @param {string} msg error message |
| | | * @memberOf editable-form |
| | | */ |
| | | $setError: function(name, msg) { |
| | | angular.forEach(this.$editables, function(editable) { |
| | | if(!name || editable.name === name) { |
| | | editable.setError(msg); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | $submit: function() { |
| | | if (this.$waiting) { |
| | | return; |
| | | } |
| | | |
| | | //clear errors |
| | | this.$setError(null, ''); |
| | | |
| | | //children onbeforesave |
| | | var pc = editablePromiseCollection(); |
| | | angular.forEach(this.$editables, function(editable) { |
| | | pc.when(editable.onbeforesave()); |
| | | }); |
| | | |
| | | /* |
| | | onbeforesave result: |
| | | - true/undefined: save data and close form |
| | | - false: close form without saving |
| | | - string: keep form open and show error |
| | | */ |
| | | pc.then({ |
| | | onWait: angular.bind(this, this.$setWaiting), |
| | | onTrue: angular.bind(this, checkSelf, true), |
| | | onFalse: angular.bind(this, checkSelf, false), |
| | | onString: angular.bind(this, this.$activate) |
| | | }); |
| | | |
| | | //save |
| | | function checkSelf(childrenTrue){ |
| | | var pc = editablePromiseCollection(); |
| | | pc.when(this.$onbeforesave()); |
| | | pc.then({ |
| | | onWait: angular.bind(this, this.$setWaiting), |
| | | onTrue: childrenTrue ? angular.bind(this, this.$save) : angular.bind(this, this.$hide), |
| | | onFalse: angular.bind(this, this.$hide), |
| | | onString: angular.bind(this, this.$activate) |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | $save: function() { |
| | | // write model for each editable |
| | | angular.forEach(this.$editables, function(editable) { |
| | | editable.save(); |
| | | }); |
| | | |
| | | //call onaftersave of self and children |
| | | var pc = editablePromiseCollection(); |
| | | pc.when(this.$onaftersave()); |
| | | angular.forEach(this.$editables, function(editable) { |
| | | pc.when(editable.onaftersave()); |
| | | }); |
| | | |
| | | /* |
| | | onaftersave result: |
| | | - true/undefined/false: just close form |
| | | - string: keep form open and show error |
| | | */ |
| | | pc.then({ |
| | | onWait: angular.bind(this, this.$setWaiting), |
| | | onTrue: angular.bind(this, this.$hide), |
| | | onFalse: angular.bind(this, this.$hide), |
| | | onString: angular.bind(this, this.$activate) |
| | | }); |
| | | }, |
| | | |
| | | $onshow: angular.noop, |
| | | $oncancel: angular.noop, |
| | | $onhide: angular.noop, |
| | | $onbeforesave: angular.noop, |
| | | $onaftersave: angular.noop |
| | | }; |
| | | |
| | | return function() { |
| | | return angular.extend({ |
| | | $editables: [], |
| | | /** |
| | | * Form visibility flag. |
| | | * |
| | | * @var {bool} $visible |
| | | * @memberOf editable-form |
| | | */ |
| | | $visible: false, |
| | | /** |
| | | * Form waiting flag. It becomes `true` when form is loading or saving data. |
| | | * |
| | | * @var {bool} $waiting |
| | | * @memberOf editable-form |
| | | */ |
| | | $waiting: false, |
| | | $data: {}, |
| | | _clicked: false, |
| | | _blur: null |
| | | }, base); |
| | | }; |
| | | }]); |
| | | |
| | | /** |
| | | * EditableForm directive. Should be defined in <form> containing editable controls. |
| | | * It add some usefull methods to form variable exposed to scope by `name="myform"` attribute. |
| | | * |
| | | * @namespace editable-form |
| | | */ |
| | | angular.module('xeditable').directive('editableForm', |
| | | ['$rootScope', '$parse', 'editableFormController', 'editableOptions', |
| | | function($rootScope, $parse, editableFormController, editableOptions) { |
| | | return { |
| | | restrict: 'A', |
| | | require: ['form'], |
| | | //require: ['form', 'editableForm'], |
| | | //controller: EditableFormController, |
| | | compile: function() { |
| | | return { |
| | | pre: function(scope, elem, attrs, ctrl) { |
| | | var form = ctrl[0]; |
| | | var eForm; |
| | | |
| | | //if `editableForm` has value - publish smartly under this value |
| | | //this is required only for single editor form that is created and removed |
| | | if(attrs.editableForm) { |
| | | if(scope[attrs.editableForm] && scope[attrs.editableForm].$show) { |
| | | eForm = scope[attrs.editableForm]; |
| | | angular.extend(form, eForm); |
| | | } else { |
| | | eForm = editableFormController(); |
| | | scope[attrs.editableForm] = eForm; |
| | | angular.extend(eForm, form); |
| | | } |
| | | } else { //just merge to form and publish if form has name |
| | | eForm = editableFormController(); |
| | | angular.extend(form, eForm); |
| | | } |
| | | |
| | | //read editables from buffer (that appeared before FORM tag) |
| | | var buf = $rootScope.$$editableBuffer; |
| | | var name = form.$name; |
| | | if(name && buf && buf[name]) { |
| | | angular.forEach(buf[name], function(editable) { |
| | | eForm.$addEditable(editable); |
| | | }); |
| | | delete buf[name]; |
| | | } |
| | | }, |
| | | post: function(scope, elem, attrs, ctrl) { |
| | | var eForm; |
| | | |
| | | if(attrs.editableForm && scope[attrs.editableForm] && scope[attrs.editableForm].$show) { |
| | | eForm = scope[attrs.editableForm]; |
| | | } else { |
| | | eForm = ctrl[0]; |
| | | } |
| | | |
| | | /** |
| | | * Called when form is shown. |
| | | * |
| | | * @var {method|attribute} onshow |
| | | * @memberOf editable-form |
| | | */ |
| | | if(attrs.onshow) { |
| | | eForm.$onshow = angular.bind(eForm, $parse(attrs.onshow), scope); |
| | | } |
| | | |
| | | /** |
| | | * Called when form hides after both save or cancel. |
| | | * |
| | | * @var {method|attribute} onhide |
| | | * @memberOf editable-form |
| | | */ |
| | | if(attrs.onhide) { |
| | | eForm.$onhide = angular.bind(eForm, $parse(attrs.onhide), scope); |
| | | } |
| | | |
| | | /** |
| | | * Called when form is cancelled. |
| | | * |
| | | * @var {method|attribute} oncancel |
| | | * @memberOf editable-form |
| | | */ |
| | | if(attrs.oncancel) { |
| | | eForm.$oncancel = angular.bind(eForm, $parse(attrs.oncancel), scope); |
| | | } |
| | | |
| | | /** |
| | | * Whether form initially rendered in shown state. |
| | | * |
| | | * @var {bool|attribute} shown |
| | | * @memberOf editable-form |
| | | */ |
| | | if(attrs.shown && $parse(attrs.shown)(scope)) { |
| | | eForm.$show(); |
| | | } |
| | | |
| | | /** |
| | | * Action when form losses focus. Values: `cancel|submit|ignore`. |
| | | * Default is `ignore`. |
| | | * |
| | | * @var {string|attribute} blur |
| | | * @memberOf editable-form |
| | | */ |
| | | eForm._blur = attrs.blur || editableOptions.blurForm; |
| | | |
| | | // onbeforesave, onaftersave |
| | | if(!attrs.ngSubmit && !attrs.submit) { |
| | | /** |
| | | * Called after all children `onbeforesave` callbacks but before saving form values |
| | | * to model. |
| | | * If at least one children callback returns `non-string` - it will not not be called. |
| | | * See [editable-form demo](#editable-form) for details. |
| | | * |
| | | * @var {method|attribute} onbeforesave |
| | | * @memberOf editable-form |
| | | * |
| | | */ |
| | | if(attrs.onbeforesave) { |
| | | eForm.$onbeforesave = function() { |
| | | return $parse(attrs.onbeforesave)(scope, {$data: eForm.$data}); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Called when form values are saved to model. |
| | | * See [editable-form demo](#editable-form) for details. |
| | | * |
| | | * @var {method|attribute} onaftersave |
| | | * @memberOf editable-form |
| | | * |
| | | */ |
| | | if(attrs.onaftersave) { |
| | | eForm.$onaftersave = function() { |
| | | return $parse(attrs.onaftersave)(scope, {$data: eForm.$data}); |
| | | }; |
| | | } |
| | | |
| | | elem.bind('submit', function(event) { |
| | | event.preventDefault(); |
| | | scope.$apply(function() { |
| | | eForm.$submit(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | |
| | | // click - mark form as clicked to exclude in document click handler |
| | | elem.bind('click', function(e) { |
| | | // ignore right/middle button click |
| | | if (e.which !== 1) { |
| | | return; |
| | | } |
| | | |
| | | if (eForm.$visible) { |
| | | eForm._clicked = true; |
| | | } |
| | | }); |
| | | |
| | | } |
| | | }; |
| | | } |
| | | }; |
| | | }]); |
| | | /** |
| | | * editablePromiseCollection |
| | | * |
| | | * Collect results of function calls. Shows waiting if there are promises. |
| | | * Finally, applies callbacks if: |
| | | * - onTrue(): all results are true and all promises resolved to true |
| | | * - onFalse(): at least one result is false or promise resolved to false |
| | | * - onString(): at least one result is string or promise rejected or promise resolved to string |
| | | */ |
| | | angular.module('xeditable').factory('editablePromiseCollection', ['$q', function($q) { |
| | | |
| | | function promiseCollection() { |
| | | return { |
| | | promises: [], |
| | | hasFalse: false, |
| | | hasString: false, |
| | | when: function(result, noPromise) { |
| | | if (result === false) { |
| | | this.hasFalse = true; |
| | | } else if (!noPromise && angular.isObject(result)) { |
| | | this.promises.push($q.when(result)); |
| | | } else if (angular.isString(result)){ |
| | | this.hasString = true; |
| | | } else { //result === true || result === undefined || result === null |
| | | return; |
| | | } |
| | | }, |
| | | //callbacks: onTrue, onFalse, onString |
| | | then: function(callbacks) { |
| | | callbacks = callbacks || {}; |
| | | var onTrue = callbacks.onTrue || angular.noop; |
| | | var onFalse = callbacks.onFalse || angular.noop; |
| | | var onString = callbacks.onString || angular.noop; |
| | | var onWait = callbacks.onWait || angular.noop; |
| | | |
| | | var self = this; |
| | | |
| | | if (this.promises.length) { |
| | | onWait(true); |
| | | $q.all(this.promises).then( |
| | | //all resolved |
| | | function(results) { |
| | | onWait(false); |
| | | //check all results via same `when` method (without checking promises) |
| | | angular.forEach(results, function(result) { |
| | | self.when(result, true); |
| | | }); |
| | | applyCallback(); |
| | | }, |
| | | //some rejected |
| | | function(error) { |
| | | onWait(false); |
| | | onString(); |
| | | } |
| | | ); |
| | | } else { |
| | | applyCallback(); |
| | | } |
| | | |
| | | function applyCallback() { |
| | | if (!self.hasString && !self.hasFalse) { |
| | | onTrue(); |
| | | } else if (!self.hasString && self.hasFalse) { |
| | | onFalse(); |
| | | } else { |
| | | onString(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | }; |
| | | } |
| | | |
| | | return promiseCollection; |
| | | |
| | | }]); |
| | | |
| | | /** |
| | | * editableUtils |
| | | */ |
| | | angular.module('xeditable').factory('editableUtils', [function() { |
| | | return { |
| | | indexOf: function (array, obj) { |
| | | if (array.indexOf) return array.indexOf(obj); |
| | | |
| | | for ( var i = 0; i < array.length; i++) { |
| | | if (obj === array[i]) return i; |
| | | } |
| | | return -1; |
| | | }, |
| | | |
| | | arrayRemove: function (array, value) { |
| | | var index = this.indexOf(array, value); |
| | | if (index >= 0) { |
| | | array.splice(index, 1); |
| | | } |
| | | return value; |
| | | }, |
| | | |
| | | // copy from https://github.com/angular/angular.js/blob/master/src/Angular.js |
| | | camelToDash: function(str) { |
| | | var SNAKE_CASE_REGEXP = /[A-Z]/g; |
| | | return str.replace(SNAKE_CASE_REGEXP, function(letter, pos) { |
| | | return (pos ? '-' : '') + letter.toLowerCase(); |
| | | }); |
| | | }, |
| | | |
| | | dashToCamel: function(str) { |
| | | var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; |
| | | var MOZ_HACK_REGEXP = /^moz([A-Z])/; |
| | | return str. |
| | | replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { |
| | | return offset ? letter.toUpperCase() : letter; |
| | | }). |
| | | replace(MOZ_HACK_REGEXP, 'Moz$1'); |
| | | } |
| | | }; |
| | | }]); |
| | | |
| | | /** |
| | | * editableNgOptionsParser |
| | | * |
| | | * see: https://github.com/angular/angular.js/blob/master/src/ng/directive/select.js#L131 |
| | | */ |
| | | angular.module('xeditable').factory('editableNgOptionsParser', [ |
| | | function() { |
| | | //0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888 |
| | | var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/; |
| | | |
| | | function parser(optionsExp) { |
| | | var match; |
| | | |
| | | if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) { |
| | | throw 'ng-options parse error'; |
| | | } |
| | | |
| | | var |
| | | displayFn = match[2] || match[1], |
| | | valueName = match[4] || match[6], |
| | | keyName = match[5], |
| | | groupByFn = match[3] || '', |
| | | valueFn = match[2] ? match[1] : valueName, |
| | | valuesFn = match[7], |
| | | track = match[8], |
| | | trackFn = track ? match[8] : null; |
| | | |
| | | var ngRepeat; |
| | | if (keyName === undefined) { // array |
| | | ngRepeat = valueName + ' in ' + valuesFn; |
| | | if (track !== undefined) { |
| | | ngRepeat += ' track by '+trackFn; |
| | | } |
| | | } else { // object |
| | | ngRepeat = '('+keyName+', '+valueName+') in '+valuesFn; |
| | | } |
| | | |
| | | // group not supported yet |
| | | return { |
| | | ngRepeat: ngRepeat, |
| | | locals: { |
| | | valueName: valueName, |
| | | keyName: keyName, |
| | | valueFn: valueFn, |
| | | displayFn: displayFn |
| | | } |
| | | }; |
| | | } |
| | | |
| | | return parser; |
| | | }]); |
| | | |
| | | /* |
| | | Editable themes: |
| | | - default |
| | | - bootstrap 2 |
| | | - bootstrap 3 |
| | | |
| | | Note: in postrender() `this` is instance of editableController |
| | | */ |
| | | angular.module('xeditable').factory('editableThemes', function() { |
| | | var themes = { |
| | | //default |
| | | 'default': { |
| | | formTpl: '<form class="editable-wrap"></form>', |
| | | noformTpl: '<span class="editable-wrap"></span>', |
| | | controlsTpl: '<span class="editable-controls"></span>', |
| | | inputTpl: '', |
| | | errorTpl: '<div class="editable-error" ng-show="$error" ng-bind="$error"></div>', |
| | | buttonsTpl: '<span class="editable-buttons"></span>', |
| | | submitTpl: '<button type="submit">save</button>', |
| | | cancelTpl: '<button type="button" ng-click="$form.$cancel()">cancel</button>' |
| | | }, |
| | | |
| | | //bs2 |
| | | 'bs2': { |
| | | formTpl: '<form class="form-inline editable-wrap" role="form"></form>', |
| | | noformTpl: '<span class="editable-wrap"></span>', |
| | | controlsTpl: '<div class="editable-controls controls control-group" ng-class="{\'error\': $error}"></div>', |
| | | inputTpl: '', |
| | | errorTpl: '<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>', |
| | | buttonsTpl: '<span class="editable-buttons"></span>', |
| | | submitTpl: '<button type="submit" class="btn btn-primary"><span class="icon-ok icon-white"></span></button>', |
| | | cancelTpl: '<button type="button" class="btn" ng-click="$form.$cancel()">'+ |
| | | '<span class="icon-remove"></span>'+ |
| | | '</button>' |
| | | |
| | | }, |
| | | |
| | | //bs3 |
| | | 'bs3': { |
| | | formTpl: '<form class="form-inline editable-wrap" role="form"></form>', |
| | | noformTpl: '<span class="editable-wrap"></span>', |
| | | controlsTpl: '<div class="editable-controls form-group" ng-class="{\'has-error\': $error}"></div>', |
| | | inputTpl: '', |
| | | errorTpl: '<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>', |
| | | buttonsTpl: '<span class="editable-buttons"></span>', |
| | | submitTpl: '<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-ok"></span></button>', |
| | | cancelTpl: '<button type="button" class="btn btn-default" ng-click="$form.$cancel()">'+ |
| | | '<span class="glyphicon glyphicon-remove"></span>'+ |
| | | '</button>', |
| | | |
| | | //bs3 specific prop to change buttons class: btn-sm, btn-lg |
| | | buttonsClass: '', |
| | | //bs3 specific prop to change standard inputs class: input-sm, input-lg |
| | | inputClass: '', |
| | | postrender: function() { |
| | | //apply `form-control` class to std inputs |
| | | switch(this.directiveName) { |
| | | case 'editableText': |
| | | case 'editableSelect': |
| | | case 'editableTextarea': |
| | | case 'editableEmail': |
| | | case 'editableTel': |
| | | case 'editableNumber': |
| | | case 'editableUrl': |
| | | case 'editableSearch': |
| | | case 'editableDate': |
| | | case 'editableDatetime': |
| | | case 'editableTime': |
| | | case 'editableMonth': |
| | | case 'editableWeek': |
| | | this.inputEl.addClass('form-control'); |
| | | if(this.theme.inputClass) { |
| | | // don`t apply `input-sm` and `input-lg` to select multiple |
| | | // should be fixed in bs itself! |
| | | if(this.inputEl.attr('multiple') && |
| | | (this.theme.inputClass === 'input-sm' || this.theme.inputClass === 'input-lg')) { |
| | | break; |
| | | } |
| | | this.inputEl.addClass(this.theme.inputClass); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | //apply buttonsClass (bs3 specific!) |
| | | if(this.buttonsEl && this.theme.buttonsClass) { |
| | | this.buttonsEl.find('button').addClass(this.theme.buttonsClass); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | return themes; |
| | | }); |
New file |
| | |
| | | /*! |
| | | angular-xeditable - 0.1.8 |
| | | Edit-in-place for angular.js |
| | | Build date: 2014-01-10 |
| | | */ |
| | | angular.module("xeditable",[]).value("editableOptions",{theme:"default",buttons:"right",blurElem:"cancel",blurForm:"ignore",activate:"focus"}),angular.module("xeditable").directive("editableBsdate",["editableDirectiveFactory",function(a){return a({directiveName:"editableBsdate",inputTpl:'<input type="text">'})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"<timepicker></timepicker>",render:function(){this.parent.render.call(this);var a=angular.element('<div class="well well-small" style="display:inline-block;"></div>');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'<input type="checkbox">',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap("<label></label>"),this.inputEl.after(angular.element("<span></span>").text(this.attrs.eTitle)))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"<span></span>",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='<label ng-repeat="'+a.ngRepeat+'">'+'<input type="checkbox" checklist-model="$parent.$data" checklist-value="'+a.locals.valueFn+'">'+'<span ng-bind="'+a.locals.displayFn+'"></span></label>';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),function(){var a="text|email|tel|number|url|search|color|date|datetime|time|month|week".split("|");angular.forEach(a,function(a){var b="editable"+a.charAt(0).toUpperCase()+a.slice(1);angular.module("xeditable").directive(b,["editableDirectiveFactory",function(c){return c({directiveName:b,inputTpl:'<input type="'+a+'">'})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'<input type="range" id="range" name="range">',render:function(){this.parent.render.call(this),this.inputEl.after("<output>{{$data}}</output>")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"<span></span>",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='<label ng-repeat="'+a.ngRepeat+'">'+'<input type="radio" ng-model="$parent.$data" value="{{'+a.locals.valueFn+'}}">'+'<span ng-bind="'+a.locals.displayFn+'"></span></label>';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"<select></select>",autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"<textarea></textarea>",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j){var k,l,m=this;m.scope=a,m.elem=d,m.attrs=c,m.inputEl=null,m.editorEl=null,m.single=!0,m.error="",m.theme=f[g.theme]||f["default"],m.parent={},m.inputTpl="",m.directiveName="",m.useCopy=!1,m.single=null,m.buttons="right",m.init=function(b){if(m.single=b,m.name=c.eName||c[m.directiveName],!c[m.directiveName])throw"You should provide value for `"+m.directiveName+"` in editable element!";k=e(c[m.directiveName]),m.buttons=m.single?m.attrs.buttons||g.buttons:"no",c.eName&&m.scope.$watch("$data",function(a){m.scope.$form.$data[c.eName]=a}),c.onshow&&(m.onshow=function(){return m.catchError(e(c.onshow)(a))}),c.onhide&&(m.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(m.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(m.onbeforesave=function(){return m.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(m.onaftersave=function(){return m.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[m.directiveName],function(){m.handleEmpty()})},m.render=function(){var a=m.theme;m.inputEl=angular.element(m.inputTpl),m.controlsEl=angular.element(a.controlsTpl),m.controlsEl.append(m.inputEl),"no"!==m.buttons&&(m.buttonsEl=angular.element(a.buttonsTpl),m.submitEl=angular.element(a.submitTpl),m.cancelEl=angular.element(a.cancelTpl),m.buttonsEl.append(m.submitEl).append(m.cancelEl),m.controlsEl.append(m.buttonsEl),m.inputEl.addClass("editable-has-buttons")),m.errorEl=angular.element(a.errorTpl),m.controlsEl.append(m.errorEl),m.editorEl=angular.element(m.single?a.formTpl:a.noformTpl),m.editorEl.append(m.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var h=""===c[d]?e:c[d];m.inputEl.attr(e,h)}}m.inputEl.addClass("editable-input"),m.inputEl.attr("ng-model","$data"),m.editorEl.addClass(b.camelToDash(m.directiveName)),m.single&&(m.editorEl.attr("editable-form","$form"),m.editorEl.attr("blur",m.attrs.blur||("no"===m.buttons?"cancel":g.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(m)},m.setLocalValue=function(){m.scope.$data=m.useCopy?angular.copy(k(a.$parent)):k(a.$parent)},m.show=function(){return m.setLocalValue(),m.render(),d.after(m.editorEl),i(m.editorEl)(a),m.addListeners(),d.addClass("editable-hide"),m.onshow()},m.hide=function(){return m.editorEl.remove(),d.removeClass("editable-hide"),m.onhide()},m.cancel=function(){m.oncancel()},m.addListeners=function(){m.inputEl.bind("keyup",function(a){if(m.single)switch(a.keyCode){case 27:m.scope.$apply(function(){m.scope.$form.$cancel()})}}),m.single&&"no"===m.buttons&&m.autosubmit(),m.editorEl.bind("click",function(a){1===a.which&&m.scope.$form.$visible&&(m.scope.$form._clicked=!0)})},m.setWaiting=function(a){a?(l=!m.inputEl.attr("disabled")&&!m.inputEl.attr("ng-disabled")&&!m.inputEl.attr("ng-enabled"),l&&(m.inputEl.attr("disabled","disabled"),m.buttonsEl&&m.buttonsEl.find("button").attr("disabled","disabled"))):l&&(m.inputEl.removeAttr("disabled"),m.buttonsEl&&m.buttonsEl.find("button").removeAttr("disabled"))},m.activate=function(){setTimeout(function(){var a=m.inputEl[0];"focus"===g.activate&&a.focus&&a.focus(),"select"===g.activate&&a.select&&a.select()},0)},m.setError=function(b){angular.isObject(b)||(a.$error=b,m.error=b)},m.catchError=function(a,b){return angular.isObject(a)&&b!==!0?j.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},m.save=function(){k.assign(a.$parent,angular.copy(m.scope.$data))},m.handleEmpty=function(){var b=k(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},m.autosubmit=angular.noop,m.onshow=angular.noop,m.onhide=angular.noop,m.oncancel=angular.noop,m.onbeforesave=angular.noop,m.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController",function(a,b,c,d,e,f,g){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,h,i){var j,k=i[0],l=!1;if(i[1])j=i[1],l=!0;else if(h.eForm){var m=a(h.eForm)(c);if(m)j=m,l=!0;else for(var n=0;n<e[0].forms.length;n++)if(e[0].forms[n].name===h.eForm){j=null,l=!0;break}}if(angular.forEach(b,function(a,b){void 0!==k[b]&&(k.parent[b]=k[b])}),angular.extend(k,b),k.init(!l),c.$editable=k,f.addClass("editable"),l)if(j){if(c.$form=j,!c.$form.$addEditable)throw"Form with editable elements should have `editable-form` attribute.";c.$form.$addEditable(k)}else d.$$editableBuffer=d.$$editableBuffer||{},d.$$editableBuffer[h.eForm]=d.$$editableBuffer[h.eForm]||[],d.$$editableBuffer[h.eForm].push(k),c.$form=null;else c.$form=g(),c.$form.$addEditable(k),h.eForm&&(c.$parent[h.eForm]=c.$form),h.eForm||(f.addClass("editable-click"),f.bind("click",function(a){a.preventDefault(),a.editable=k,c.$apply(function(){c.$form.$show()})}))}}}}]),angular.module("xeditable").factory("editableFormController",["$parse","$document","$rootScope","editablePromiseCollection","editableUtils",function(a,b,c,d,e){var f=[];b.bind("click",function(a){if(1===a.which){for(var b=[],d=[],e=0;e<f.length;e++)f[e]._clicked?f[e]._clicked=!1:f[e].$waiting||("cancel"===f[e]._blur&&b.push(f[e]),"submit"===f[e]._blur&&d.push(f[e]));(b.length||d.length)&&c.$apply(function(){angular.forEach(b,function(a){a.$cancel()}),angular.forEach(d,function(a){a.$submit()})})}});var g={$addEditable:function(a){this.$editables.push(a),a.elem.bind("$destroy",angular.bind(this,this.$removeEditable,a)),a.scope.$form||(a.scope.$form=this),this.$visible&&a.catchError(a.show())},$removeEditable:function(a){for(var b=0;b<this.$editables.length;b++)if(this.$editables[b]===a)return this.$editables.splice(b,1),void 0},$show:function(){if(!this.$visible){this.$visible=!0;var a=d();a.when(this.$onshow()),this.$setError(null,""),angular.forEach(this.$editables,function(b){a.when(b.show())}),a.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,this.$activate),onFalse:angular.bind(this,this.$activate),onString:angular.bind(this,this.$activate)}),setTimeout(angular.bind(this,function(){this._clicked=!1,-1===e.indexOf(f,this)&&f.push(this)}),0)}},$activate:function(a){var b;if(this.$editables.length){if(angular.isString(a))for(b=0;b<this.$editables.length;b++)if(this.$editables[b].name===a)return this.$editables[b].activate(),void 0;for(b=0;b<this.$editables.length;b++)if(this.$editables[b].error)return this.$editables[b].activate(),void 0;this.$editables[0].activate()}},$hide:function(){this.$visible&&(this.$visible=!1,this.$onhide(),angular.forEach(this.$editables,function(a){a.hide()}),e.arrayRemove(f,this))},$cancel:function(){this.$visible&&(this.$oncancel(),angular.forEach(this.$editables,function(a){a.cancel()}),this.$hide())},$setWaiting:function(a){this.$waiting=!!a,angular.forEach(this.$editables,function(b){b.setWaiting(!!a)})},$setError:function(a,b){angular.forEach(this.$editables,function(c){a&&c.name!==a||c.setError(b)})},$submit:function(){function a(a){var b=d();b.when(this.$onbeforesave()),b.then({onWait:angular.bind(this,this.$setWaiting),onTrue:a?angular.bind(this,this.$save):angular.bind(this,this.$hide),onFalse:angular.bind(this,this.$hide),onString:angular.bind(this,this.$activate)})}if(!this.$waiting){this.$setError(null,"");var b=d();angular.forEach(this.$editables,function(a){b.when(a.onbeforesave())}),b.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,a,!0),onFalse:angular.bind(this,a,!1),onString:angular.bind(this,this.$activate)})}},$save:function(){angular.forEach(this.$editables,function(a){a.save()});var a=d();a.when(this.$onaftersave()),angular.forEach(this.$editables,function(b){a.when(b.onaftersave())}),a.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,this.$hide),onFalse:angular.bind(this,this.$hide),onString:angular.bind(this,this.$activate)})},$onshow:angular.noop,$oncancel:angular.noop,$onhide:angular.noop,$onbeforesave:angular.noop,$onaftersave:angular.noop};return function(){return angular.extend({$editables:[],$visible:!1,$waiting:!1,$data:{},_clicked:!1,_blur:null},g)}}]),angular.module("xeditable").directive("editableForm",["$rootScope","$parse","editableFormController","editableOptions",function(a,b,c,d){return{restrict:"A",require:["form"],compile:function(){return{pre:function(b,d,e,f){var g,h=f[0];e.editableForm?b[e.editableForm]&&b[e.editableForm].$show?(g=b[e.editableForm],angular.extend(h,g)):(g=c(),b[e.editableForm]=g,angular.extend(g,h)):(g=c(),angular.extend(h,g));var i=a.$$editableBuffer,j=h.$name;j&&i&&i[j]&&(angular.forEach(i[j],function(a){g.$addEditable(a)}),delete i[j])},post:function(a,c,e,f){var g;g=e.editableForm&&a[e.editableForm]&&a[e.editableForm].$show?a[e.editableForm]:f[0],e.onshow&&(g.$onshow=angular.bind(g,b(e.onshow),a)),e.onhide&&(g.$onhide=angular.bind(g,b(e.onhide),a)),e.oncancel&&(g.$oncancel=angular.bind(g,b(e.oncancel),a)),e.shown&&b(e.shown)(a)&&g.$show(),g._blur=e.blur||d.blurForm,e.ngSubmit||e.submit||(e.onbeforesave&&(g.$onbeforesave=function(){return b(e.onbeforesave)(a,{$data:g.$data})}),e.onaftersave&&(g.$onaftersave=function(){return b(e.onaftersave)(a,{$data:g.$data})}),c.bind("submit",function(b){b.preventDefault(),a.$apply(function(){g.$submit()})})),c.bind("click",function(a){1===a.which&&g.$visible&&(g._clicked=!0)})}}}}}]),angular.module("xeditable").factory("editablePromiseCollection",["$q",function(a){function b(){return{promises:[],hasFalse:!1,hasString:!1,when:function(b,c){if(b===!1)this.hasFalse=!0;else if(!c&&angular.isObject(b))this.promises.push(a.when(b));else{if(!angular.isString(b))return;this.hasString=!0}},then:function(b){function c(){h.hasString||h.hasFalse?!h.hasString&&h.hasFalse?e():f():d()}b=b||{};var d=b.onTrue||angular.noop,e=b.onFalse||angular.noop,f=b.onString||angular.noop,g=b.onWait||angular.noop,h=this;this.promises.length?(g(!0),a.all(this.promises).then(function(a){g(!1),angular.forEach(a,function(a){h.when(a,!0)}),c()},function(){g(!1),f()})):c()}}}return b}]),angular.module("xeditable").factory("editableUtils",[function(){return{indexOf:function(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0;c<a.length;c++)if(b===a[c])return c;return-1},arrayRemove:function(a,b){var c=this.indexOf(a,b);return c>=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'<form class="editable-wrap"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<span class="editable-controls"></span>',inputTpl:"",errorTpl:'<div class="editable-error" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit">save</button>',cancelTpl:'<button type="button" ng-click="$form.$cancel()">cancel</button>'},bs2:{formTpl:'<form class="form-inline editable-wrap" role="form"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<div class="editable-controls controls control-group" ng-class="{\'error\': $error}"></div>',inputTpl:"",errorTpl:'<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit" class="btn btn-primary"><span class="icon-ok icon-white"></span></button>',cancelTpl:'<button type="button" class="btn" ng-click="$form.$cancel()"><span class="icon-remove"></span></button>'},bs3:{formTpl:'<form class="form-inline editable-wrap" role="form"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<div class="editable-controls form-group" ng-class="{\'has-error\': $error}"></div>',inputTpl:"",errorTpl:'<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-ok"></span></button>',cancelTpl:'<button type="button" class="btn btn-default" ng-click="$form.$cancel()"><span class="glyphicon glyphicon-remove"></span></button>',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableTime":case"editableMonth":case"editableWeek":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}}};return a}); |
New file |
| | |
| | | /** |
| | | * @license AngularJS v1.2.18 |
| | | * (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | * License: MIT |
| | | */ |
| | | (function(window, angular, undefined) {'use strict'; |
| | | |
| | | /* jshint maxlen: false */ |
| | | |
| | | /** |
| | | * @ngdoc module |
| | | * @name ngAnimate |
| | | * @description |
| | | * |
| | | * # ngAnimate |
| | | * |
| | | * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. |
| | | * |
| | | * |
| | | * <div doc-module-components="ngAnimate"></div> |
| | | * |
| | | * # Usage |
| | | * |
| | | * To see animations in action, all that is required is to define the appropriate CSS classes |
| | | * or to register a JavaScript animation via the myModule.animation() function. The directives that support animation automatically are: |
| | | * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation |
| | | * by using the `$animate` service. |
| | | * |
| | | * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives: |
| | | * |
| | | * | Directive | Supported Animations | |
| | | * |---------------------------------------------------------- |----------------------------------------------------| |
| | | * | {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave and move | |
| | | * | {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave | |
| | | * | {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave | |
| | | * | {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave | |
| | | * | {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave | |
| | | * | {@link ng.directive:ngClass#usage_animations ngClass} | add and remove | |
| | | * | {@link ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) | |
| | | * | {@link ng.directive:form#usage_animations form} | add and remove (dirty, pristine, valid, invalid & all other validations) | |
| | | * | {@link ng.directive:ngModel#usage_animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | |
| | | * |
| | | * You can find out more information about animations upon visiting each directive page. |
| | | * |
| | | * Below is an example of how to apply animations to a directive that supports animation hooks: |
| | | * |
| | | * ```html |
| | | * <style type="text/css"> |
| | | * .slide.ng-enter, .slide.ng-leave { |
| | | * -webkit-transition:0.5s linear all; |
| | | * transition:0.5s linear all; |
| | | * } |
| | | * |
| | | * .slide.ng-enter { } /* starting animations for enter */ |
| | | * .slide.ng-enter-active { } /* terminal animations for enter */ |
| | | * .slide.ng-leave { } /* starting animations for leave */ |
| | | * .slide.ng-leave-active { } /* terminal animations for leave */ |
| | | * </style> |
| | | * |
| | | * <!-- |
| | | * the animate service will automatically add .ng-enter and .ng-leave to the element |
| | | * to trigger the CSS transition/animations |
| | | * --> |
| | | * <ANY class="slide" ng-include="..."></ANY> |
| | | * ``` |
| | | * |
| | | * Keep in mind that if an animation is running, any child elements cannot be animated until the parent element's |
| | | * animation has completed. |
| | | * |
| | | * <h2>CSS-defined Animations</h2> |
| | | * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes |
| | | * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported |
| | | * and can be used to play along with this naming structure. |
| | | * |
| | | * The following code below demonstrates how to perform animations using **CSS transitions** with Angular: |
| | | * |
| | | * ```html |
| | | * <style type="text/css"> |
| | | * /* |
| | | * The animate class is apart of the element and the ng-enter class |
| | | * is attached to the element once the enter animation event is triggered |
| | | * */ |
| | | * .reveal-animation.ng-enter { |
| | | * -webkit-transition: 1s linear all; /* Safari/Chrome */ |
| | | * transition: 1s linear all; /* All other modern browsers and IE10+ */ |
| | | * |
| | | * /* The animation preparation code */ |
| | | * opacity: 0; |
| | | * } |
| | | * |
| | | * /* |
| | | * Keep in mind that you want to combine both CSS |
| | | * classes together to avoid any CSS-specificity |
| | | * conflicts |
| | | * */ |
| | | * .reveal-animation.ng-enter.ng-enter-active { |
| | | * /* The animation code itself */ |
| | | * opacity: 1; |
| | | * } |
| | | * </style> |
| | | * |
| | | * <div class="view-container"> |
| | | * <div ng-view class="reveal-animation"></div> |
| | | * </div> |
| | | * ``` |
| | | * |
| | | * The following code below demonstrates how to perform animations using **CSS animations** with Angular: |
| | | * |
| | | * ```html |
| | | * <style type="text/css"> |
| | | * .reveal-animation.ng-enter { |
| | | * -webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */ |
| | | * animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */ |
| | | * } |
| | | * @-webkit-keyframes enter_sequence { |
| | | * from { opacity:0; } |
| | | * to { opacity:1; } |
| | | * } |
| | | * @keyframes enter_sequence { |
| | | * from { opacity:0; } |
| | | * to { opacity:1; } |
| | | * } |
| | | * </style> |
| | | * |
| | | * <div class="view-container"> |
| | | * <div ng-view class="reveal-animation"></div> |
| | | * </div> |
| | | * ``` |
| | | * |
| | | * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing. |
| | | * |
| | | * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add |
| | | * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically |
| | | * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be |
| | | * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end |
| | | * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element |
| | | * has no CSS transition/animation classes applied to it. |
| | | * |
| | | * <h3>CSS Staggering Animations</h3> |
| | | * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a |
| | | * curtain-like effect. The ngAnimate module, as of 1.2.0, supports staggering animations and the stagger effect can be |
| | | * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for |
| | | * the animation. The style property expected within the stagger class can either be a **transition-delay** or an |
| | | * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). |
| | | * |
| | | * ```css |
| | | * .my-animation.ng-enter { |
| | | * /* standard transition code */ |
| | | * -webkit-transition: 1s linear all; |
| | | * transition: 1s linear all; |
| | | * opacity:0; |
| | | * } |
| | | * .my-animation.ng-enter-stagger { |
| | | * /* this will have a 100ms delay between each successive leave animation */ |
| | | * -webkit-transition-delay: 0.1s; |
| | | * transition-delay: 0.1s; |
| | | * |
| | | * /* in case the stagger doesn't work then these two values |
| | | * must be set to 0 to avoid an accidental CSS inheritance */ |
| | | * -webkit-transition-duration: 0s; |
| | | * transition-duration: 0s; |
| | | * } |
| | | * .my-animation.ng-enter.ng-enter-active { |
| | | * /* standard transition styles */ |
| | | * opacity:1; |
| | | * } |
| | | * ``` |
| | | * |
| | | * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations |
| | | * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this |
| | | * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation |
| | | * will also be reset if more than 10ms has passed after the last animation has been fired. |
| | | * |
| | | * The following code will issue the **ng-leave-stagger** event on the element provided: |
| | | * |
| | | * ```js |
| | | * var kids = parent.children(); |
| | | * |
| | | * $animate.leave(kids[0]); //stagger index=0 |
| | | * $animate.leave(kids[1]); //stagger index=1 |
| | | * $animate.leave(kids[2]); //stagger index=2 |
| | | * $animate.leave(kids[3]); //stagger index=3 |
| | | * $animate.leave(kids[4]); //stagger index=4 |
| | | * |
| | | * $timeout(function() { |
| | | * //stagger has reset itself |
| | | * $animate.leave(kids[5]); //stagger index=0 |
| | | * $animate.leave(kids[6]); //stagger index=1 |
| | | * }, 100, false); |
| | | * ``` |
| | | * |
| | | * Stagger animations are currently only supported within CSS-defined animations. |
| | | * |
| | | * <h2>JavaScript-defined Animations</h2> |
| | | * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not |
| | | * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module. |
| | | * |
| | | * ```js |
| | | * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application. |
| | | * var ngModule = angular.module('YourApp', ['ngAnimate']); |
| | | * ngModule.animation('.my-crazy-animation', function() { |
| | | * return { |
| | | * enter: function(element, done) { |
| | | * //run the animation here and call done when the animation is complete |
| | | * return function(cancelled) { |
| | | * //this (optional) function will be called when the animation |
| | | * //completes or when the animation is cancelled (the cancelled |
| | | * //flag will be set to true if cancelled). |
| | | * }; |
| | | * }, |
| | | * leave: function(element, done) { }, |
| | | * move: function(element, done) { }, |
| | | * |
| | | * //animation that can be triggered before the class is added |
| | | * beforeAddClass: function(element, className, done) { }, |
| | | * |
| | | * //animation that can be triggered after the class is added |
| | | * addClass: function(element, className, done) { }, |
| | | * |
| | | * //animation that can be triggered before the class is removed |
| | | * beforeRemoveClass: function(element, className, done) { }, |
| | | * |
| | | * //animation that can be triggered after the class is removed |
| | | * removeClass: function(element, className, done) { } |
| | | * }; |
| | | * }); |
| | | * ``` |
| | | * |
| | | * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run |
| | | * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits |
| | | * the element's CSS class attribute value and then run the matching animation event function (if found). |
| | | * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will |
| | | * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported). |
| | | * |
| | | * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned. |
| | | * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run, |
| | | * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation |
| | | * or transition code that is defined via a stylesheet). |
| | | * |
| | | */ |
| | | |
| | | angular.module('ngAnimate', ['ng']) |
| | | |
| | | /** |
| | | * @ngdoc provider |
| | | * @name $animateProvider |
| | | * @description |
| | | * |
| | | * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module. |
| | | * When an animation is triggered, the $animate service will query the $animate service to find any animations that match |
| | | * the provided name value. |
| | | * |
| | | * Requires the {@link ngAnimate `ngAnimate`} module to be installed. |
| | | * |
| | | * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. |
| | | * |
| | | */ |
| | | |
| | | //this private service is only used within CSS-enabled animations |
| | | //IE8 + IE9 do not support rAF natively, but that is fine since they |
| | | //also don't support transitions and keyframes which means that the code |
| | | //below will never be used by the two browsers. |
| | | .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) { |
| | | var bod = $document[0].body; |
| | | return function(fn) { |
| | | //the returned function acts as the cancellation function |
| | | return $$rAF(function() { |
| | | //the line below will force the browser to perform a repaint |
| | | //so that all the animated elements within the animation frame |
| | | //will be properly updated and drawn on screen. This is |
| | | //required to perform multi-class CSS based animations with |
| | | //Firefox. DO NOT REMOVE THIS LINE. |
| | | var a = bod.offsetWidth + 1; |
| | | fn(); |
| | | }); |
| | | }; |
| | | }]) |
| | | |
| | | .config(['$provide', '$animateProvider', function($provide, $animateProvider) { |
| | | var noop = angular.noop; |
| | | var forEach = angular.forEach; |
| | | var selectors = $animateProvider.$$selectors; |
| | | |
| | | var ELEMENT_NODE = 1; |
| | | var NG_ANIMATE_STATE = '$$ngAnimateState'; |
| | | var NG_ANIMATE_CLASS_NAME = 'ng-animate'; |
| | | var rootAnimateState = {running: true}; |
| | | |
| | | function extractElementNode(element) { |
| | | for(var i = 0; i < element.length; i++) { |
| | | var elm = element[i]; |
| | | if(elm.nodeType == ELEMENT_NODE) { |
| | | return elm; |
| | | } |
| | | } |
| | | } |
| | | |
| | | function prepareElement(element) { |
| | | return element && angular.element(element); |
| | | } |
| | | |
| | | function stripCommentsFromElement(element) { |
| | | return angular.element(extractElementNode(element)); |
| | | } |
| | | |
| | | function isMatchingElement(elm1, elm2) { |
| | | return extractElementNode(elm1) == extractElementNode(elm2); |
| | | } |
| | | |
| | | $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', |
| | | function($delegate, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document) { |
| | | |
| | | var globalAnimationCounter = 0; |
| | | $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); |
| | | |
| | | // disable animations during bootstrap, but once we bootstrapped, wait again |
| | | // for another digest until enabling animations. The reason why we digest twice |
| | | // is because all structural animations (enter, leave and move) all perform a |
| | | // post digest operation before animating. If we only wait for a single digest |
| | | // to pass then the structural animation would render its animation on page load. |
| | | // (which is what we're trying to avoid when the application first boots up.) |
| | | $rootScope.$$postDigest(function() { |
| | | $rootScope.$$postDigest(function() { |
| | | rootAnimateState.running = false; |
| | | }); |
| | | }); |
| | | |
| | | var classNameFilter = $animateProvider.classNameFilter(); |
| | | var isAnimatableClassName = !classNameFilter |
| | | ? function() { return true; } |
| | | : function(className) { |
| | | return classNameFilter.test(className); |
| | | }; |
| | | |
| | | function lookup(name) { |
| | | if (name) { |
| | | var matches = [], |
| | | flagMap = {}, |
| | | classes = name.substr(1).split('.'); |
| | | |
| | | //the empty string value is the default animation |
| | | //operation which performs CSS transition and keyframe |
| | | //animations sniffing. This is always included for each |
| | | //element animation procedure if the browser supports |
| | | //transitions and/or keyframe animations. The default |
| | | //animation is added to the top of the list to prevent |
| | | //any previous animations from affecting the element styling |
| | | //prior to the element being animated. |
| | | if ($sniffer.transitions || $sniffer.animations) { |
| | | matches.push($injector.get(selectors[''])); |
| | | } |
| | | |
| | | for(var i=0; i < classes.length; i++) { |
| | | var klass = classes[i], |
| | | selectorFactoryName = selectors[klass]; |
| | | if(selectorFactoryName && !flagMap[klass]) { |
| | | matches.push($injector.get(selectorFactoryName)); |
| | | flagMap[klass] = true; |
| | | } |
| | | } |
| | | return matches; |
| | | } |
| | | } |
| | | |
| | | function animationRunner(element, animationEvent, className) { |
| | | //transcluded directives may sometimes fire an animation using only comment nodes |
| | | //best to catch this early on to prevent any animation operations from occurring |
| | | var node = element[0]; |
| | | if(!node) { |
| | | return; |
| | | } |
| | | |
| | | var isSetClassOperation = animationEvent == 'setClass'; |
| | | var isClassBased = isSetClassOperation || |
| | | animationEvent == 'addClass' || |
| | | animationEvent == 'removeClass'; |
| | | |
| | | var classNameAdd, classNameRemove; |
| | | if(angular.isArray(className)) { |
| | | classNameAdd = className[0]; |
| | | classNameRemove = className[1]; |
| | | className = classNameAdd + ' ' + classNameRemove; |
| | | } |
| | | |
| | | var currentClassName = element.attr('class'); |
| | | var classes = currentClassName + ' ' + className; |
| | | if(!isAnimatableClassName(classes)) { |
| | | return; |
| | | } |
| | | |
| | | var beforeComplete = noop, |
| | | beforeCancel = [], |
| | | before = [], |
| | | afterComplete = noop, |
| | | afterCancel = [], |
| | | after = []; |
| | | |
| | | var animationLookup = (' ' + classes).replace(/\s+/g,'.'); |
| | | forEach(lookup(animationLookup), function(animationFactory) { |
| | | var created = registerAnimation(animationFactory, animationEvent); |
| | | if(!created && isSetClassOperation) { |
| | | registerAnimation(animationFactory, 'addClass'); |
| | | registerAnimation(animationFactory, 'removeClass'); |
| | | } |
| | | }); |
| | | |
| | | function registerAnimation(animationFactory, event) { |
| | | var afterFn = animationFactory[event]; |
| | | var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)]; |
| | | if(afterFn || beforeFn) { |
| | | if(event == 'leave') { |
| | | beforeFn = afterFn; |
| | | //when set as null then animation knows to skip this phase |
| | | afterFn = null; |
| | | } |
| | | after.push({ |
| | | event : event, fn : afterFn |
| | | }); |
| | | before.push({ |
| | | event : event, fn : beforeFn |
| | | }); |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | function run(fns, cancellations, allCompleteFn) { |
| | | var animations = []; |
| | | forEach(fns, function(animation) { |
| | | animation.fn && animations.push(animation); |
| | | }); |
| | | |
| | | var count = 0; |
| | | function afterAnimationComplete(index) { |
| | | if(cancellations) { |
| | | (cancellations[index] || noop)(); |
| | | if(++count < animations.length) return; |
| | | cancellations = null; |
| | | } |
| | | allCompleteFn(); |
| | | } |
| | | |
| | | //The code below adds directly to the array in order to work with |
| | | //both sync and async animations. Sync animations are when the done() |
| | | //operation is called right away. DO NOT REFACTOR! |
| | | forEach(animations, function(animation, index) { |
| | | var progress = function() { |
| | | afterAnimationComplete(index); |
| | | }; |
| | | switch(animation.event) { |
| | | case 'setClass': |
| | | cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress)); |
| | | break; |
| | | case 'addClass': |
| | | cancellations.push(animation.fn(element, classNameAdd || className, progress)); |
| | | break; |
| | | case 'removeClass': |
| | | cancellations.push(animation.fn(element, classNameRemove || className, progress)); |
| | | break; |
| | | default: |
| | | cancellations.push(animation.fn(element, progress)); |
| | | break; |
| | | } |
| | | }); |
| | | |
| | | if(cancellations && cancellations.length === 0) { |
| | | allCompleteFn(); |
| | | } |
| | | } |
| | | |
| | | return { |
| | | node : node, |
| | | event : animationEvent, |
| | | className : className, |
| | | isClassBased : isClassBased, |
| | | isSetClassOperation : isSetClassOperation, |
| | | before : function(allCompleteFn) { |
| | | beforeComplete = allCompleteFn; |
| | | run(before, beforeCancel, function() { |
| | | beforeComplete = noop; |
| | | allCompleteFn(); |
| | | }); |
| | | }, |
| | | after : function(allCompleteFn) { |
| | | afterComplete = allCompleteFn; |
| | | run(after, afterCancel, function() { |
| | | afterComplete = noop; |
| | | allCompleteFn(); |
| | | }); |
| | | }, |
| | | cancel : function() { |
| | | if(beforeCancel) { |
| | | forEach(beforeCancel, function(cancelFn) { |
| | | (cancelFn || noop)(true); |
| | | }); |
| | | beforeComplete(true); |
| | | } |
| | | if(afterCancel) { |
| | | forEach(afterCancel, function(cancelFn) { |
| | | (cancelFn || noop)(true); |
| | | }); |
| | | afterComplete(true); |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $animate |
| | | * @kind function |
| | | * |
| | | * @description |
| | | * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations. |
| | | * When any of these operations are run, the $animate service |
| | | * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object) |
| | | * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run. |
| | | * |
| | | * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives |
| | | * will work out of the box without any extra configuration. |
| | | * |
| | | * Requires the {@link ngAnimate `ngAnimate`} module to be installed. |
| | | * |
| | | * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. |
| | | * |
| | | */ |
| | | return { |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#enter |
| | | * @kind function |
| | | * |
| | | * @description |
| | | * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once |
| | | * the animation is started, the following CSS classes will be present on the element for the duration of the animation: |
| | | * |
| | | * Below is a breakdown of each step that occurs during enter animation: |
| | | * |
| | | * | Animation Step | What the element class attribute looks like | |
| | | * |----------------------------------------------------------------------------------------------|---------------------------------------------| |
| | | * | 1. $animate.enter(...) is called | class="my-animation" | |
| | | * | 2. element is inserted into the parentElement element or beside the afterElement element | class="my-animation" | |
| | | * | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | |
| | | * | 4. the .ng-enter class is added to the element | class="my-animation ng-animate ng-enter" | |
| | | * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-enter" | |
| | | * | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-enter" | |
| | | * | 7. the .ng-enter-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" | |
| | | * | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" | |
| | | * | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | |
| | | * | 10. The doneCallback() callback is fired (if provided) | class="my-animation" | |
| | | * |
| | | * @param {DOMElement} element the element that will be the focus of the enter animation |
| | | * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation |
| | | * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation |
| | | * @param {function()=} doneCallback the callback function that will be called once the animation is complete |
| | | */ |
| | | enter : function(element, parentElement, afterElement, doneCallback) { |
| | | element = angular.element(element); |
| | | parentElement = prepareElement(parentElement); |
| | | afterElement = prepareElement(afterElement); |
| | | |
| | | this.enabled(false, element); |
| | | $delegate.enter(element, parentElement, afterElement); |
| | | $rootScope.$$postDigest(function() { |
| | | element = stripCommentsFromElement(element); |
| | | performAnimation('enter', 'ng-enter', element, parentElement, afterElement, noop, doneCallback); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#leave |
| | | * @kind function |
| | | * |
| | | * @description |
| | | * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once |
| | | * the animation is started, the following CSS classes will be added for the duration of the animation: |
| | | * |
| | | * Below is a breakdown of each step that occurs during leave animation: |
| | | * |
| | | * | Animation Step | What the element class attribute looks like | |
| | | * |----------------------------------------------------------------------------------------------|---------------------------------------------| |
| | | * | 1. $animate.leave(...) is called | class="my-animation" | |
| | | * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | |
| | | * | 3. the .ng-leave class is added to the element | class="my-animation ng-animate ng-leave" | |
| | | * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-leave" | |
| | | * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-leave" | |
| | | * | 6. the .ng-leave-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" | |
| | | * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" | |
| | | * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | |
| | | * | 9. The element is removed from the DOM | ... | |
| | | * | 10. The doneCallback() callback is fired (if provided) | ... | |
| | | * |
| | | * @param {DOMElement} element the element that will be the focus of the leave animation |
| | | * @param {function()=} doneCallback the callback function that will be called once the animation is complete |
| | | */ |
| | | leave : function(element, doneCallback) { |
| | | element = angular.element(element); |
| | | cancelChildAnimations(element); |
| | | this.enabled(false, element); |
| | | $rootScope.$$postDigest(function() { |
| | | performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() { |
| | | $delegate.leave(element); |
| | | }, doneCallback); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#move |
| | | * @kind function |
| | | * |
| | | * @description |
| | | * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or |
| | | * add the element directly after the afterElement element if present. Then the move animation will be run. Once |
| | | * the animation is started, the following CSS classes will be added for the duration of the animation: |
| | | * |
| | | * Below is a breakdown of each step that occurs during move animation: |
| | | * |
| | | * | Animation Step | What the element class attribute looks like | |
| | | * |----------------------------------------------------------------------------------------------|---------------------------------------------| |
| | | * | 1. $animate.move(...) is called | class="my-animation" | |
| | | * | 2. element is moved into the parentElement element or beside the afterElement element | class="my-animation" | |
| | | * | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | |
| | | * | 4. the .ng-move class is added to the element | class="my-animation ng-animate ng-move" | |
| | | * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-move" | |
| | | * | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-move" | |
| | | * | 7. the .ng-move-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" | |
| | | * | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" | |
| | | * | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | |
| | | * | 10. The doneCallback() callback is fired (if provided) | class="my-animation" | |
| | | * |
| | | * @param {DOMElement} element the element that will be the focus of the move animation |
| | | * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation |
| | | * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation |
| | | * @param {function()=} doneCallback the callback function that will be called once the animation is complete |
| | | */ |
| | | move : function(element, parentElement, afterElement, doneCallback) { |
| | | element = angular.element(element); |
| | | parentElement = prepareElement(parentElement); |
| | | afterElement = prepareElement(afterElement); |
| | | |
| | | cancelChildAnimations(element); |
| | | this.enabled(false, element); |
| | | $delegate.move(element, parentElement, afterElement); |
| | | $rootScope.$$postDigest(function() { |
| | | element = stripCommentsFromElement(element); |
| | | performAnimation('move', 'ng-move', element, parentElement, afterElement, noop, doneCallback); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#addClass |
| | | * |
| | | * @description |
| | | * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. |
| | | * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide |
| | | * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions |
| | | * or keyframes are defined on the -add or base CSS class). |
| | | * |
| | | * Below is a breakdown of each step that occurs during addClass animation: |
| | | * |
| | | * | Animation Step | What the element class attribute looks like | |
| | | * |------------------------------------------------------------------------------------------------|---------------------------------------------| |
| | | * | 1. $animate.addClass(element, 'super') is called | class="my-animation" | |
| | | * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | |
| | | * | 3. the .super-add class are added to the element | class="my-animation ng-animate super-add" | |
| | | * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super-add" | |
| | | * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate super-add" | |
| | | * | 6. the .super, .super-add-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super super-add super-add-active" | |
| | | * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation super super-add super-add-active" | |
| | | * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation super" | |
| | | * | 9. The super class is kept on the element | class="my-animation super" | |
| | | * | 10. The doneCallback() callback is fired (if provided) | class="my-animation super" | |
| | | * |
| | | * @param {DOMElement} element the element that will be animated |
| | | * @param {string} className the CSS class that will be added to the element and then animated |
| | | * @param {function()=} doneCallback the callback function that will be called once the animation is complete |
| | | */ |
| | | addClass : function(element, className, doneCallback) { |
| | | element = angular.element(element); |
| | | element = stripCommentsFromElement(element); |
| | | performAnimation('addClass', className, element, null, null, function() { |
| | | $delegate.addClass(element, className); |
| | | }, doneCallback); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#removeClass |
| | | * |
| | | * @description |
| | | * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value |
| | | * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in |
| | | * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if |
| | | * no CSS transitions or keyframes are defined on the -remove or base CSS classes). |
| | | * |
| | | * Below is a breakdown of each step that occurs during removeClass animation: |
| | | * |
| | | * | Animation Step | What the element class attribute looks like | |
| | | * |-----------------------------------------------------------------------------------------------|---------------------------------------------| |
| | | * | 1. $animate.removeClass(element, 'super') is called | class="my-animation super" | |
| | | * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation super ng-animate" | |
| | | * | 3. the .super-remove class are added to the element | class="my-animation super ng-animate super-remove"| |
| | | * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation super ng-animate super-remove" | |
| | | * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation super ng-animate super-remove" | |
| | | * | 6. the .super-remove-active and .ng-animate-active classes are added and .super is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" | |
| | | * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" | |
| | | * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | |
| | | * | 9. The doneCallback() callback is fired (if provided) | class="my-animation" | |
| | | * |
| | | * |
| | | * @param {DOMElement} element the element that will be animated |
| | | * @param {string} className the CSS class that will be animated and then removed from the element |
| | | * @param {function()=} doneCallback the callback function that will be called once the animation is complete |
| | | */ |
| | | removeClass : function(element, className, doneCallback) { |
| | | element = angular.element(element); |
| | | element = stripCommentsFromElement(element); |
| | | performAnimation('removeClass', className, element, null, null, function() { |
| | | $delegate.removeClass(element, className); |
| | | }, doneCallback); |
| | | }, |
| | | |
| | | /** |
| | | * |
| | | * @ngdoc function |
| | | * @name $animate#setClass |
| | | * @function |
| | | * @description Adds and/or removes the given CSS classes to and from the element. |
| | | * Once complete, the done() callback will be fired (if provided). |
| | | * @param {DOMElement} element the element which will its CSS classes changed |
| | | * removed from it |
| | | * @param {string} add the CSS classes which will be added to the element |
| | | * @param {string} remove the CSS class which will be removed from the element |
| | | * @param {Function=} done the callback function (if provided) that will be fired after the |
| | | * CSS classes have been set on the element |
| | | */ |
| | | setClass : function(element, add, remove, doneCallback) { |
| | | element = angular.element(element); |
| | | element = stripCommentsFromElement(element); |
| | | performAnimation('setClass', [add, remove], element, null, null, function() { |
| | | $delegate.setClass(element, add, remove); |
| | | }, doneCallback); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $animate#enabled |
| | | * @kind function |
| | | * |
| | | * @param {boolean=} value If provided then set the animation on or off. |
| | | * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation |
| | | * @return {boolean} Current animation state. |
| | | * |
| | | * @description |
| | | * Globally enables/disables animations. |
| | | * |
| | | */ |
| | | enabled : function(value, element) { |
| | | switch(arguments.length) { |
| | | case 2: |
| | | if(value) { |
| | | cleanup(element); |
| | | } else { |
| | | var data = element.data(NG_ANIMATE_STATE) || {}; |
| | | data.disabled = true; |
| | | element.data(NG_ANIMATE_STATE, data); |
| | | } |
| | | break; |
| | | |
| | | case 1: |
| | | rootAnimateState.disabled = !value; |
| | | break; |
| | | |
| | | default: |
| | | value = !rootAnimateState.disabled; |
| | | break; |
| | | } |
| | | return !!value; |
| | | } |
| | | }; |
| | | |
| | | /* |
| | | all animations call this shared animation triggering function internally. |
| | | The animationEvent variable refers to the JavaScript animation event that will be triggered |
| | | and the className value is the name of the animation that will be applied within the |
| | | CSS code. Element, parentElement and afterElement are provided DOM elements for the animation |
| | | and the onComplete callback will be fired once the animation is fully complete. |
| | | */ |
| | | function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) { |
| | | |
| | | var runner = animationRunner(element, animationEvent, className); |
| | | if(!runner) { |
| | | fireDOMOperation(); |
| | | fireBeforeCallbackAsync(); |
| | | fireAfterCallbackAsync(); |
| | | closeAnimation(); |
| | | return; |
| | | } |
| | | |
| | | className = runner.className; |
| | | var elementEvents = angular.element._data(runner.node); |
| | | elementEvents = elementEvents && elementEvents.events; |
| | | |
| | | if (!parentElement) { |
| | | parentElement = afterElement ? afterElement.parent() : element.parent(); |
| | | } |
| | | |
| | | var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; |
| | | var runningAnimations = ngAnimateState.active || {}; |
| | | var totalActiveAnimations = ngAnimateState.totalActive || 0; |
| | | var lastAnimation = ngAnimateState.last; |
| | | |
| | | //only allow animations if the currently running animation is not structural |
| | | //or if there is no animation running at all |
| | | var skipAnimations = runner.isClassBased ? |
| | | ngAnimateState.disabled || (lastAnimation && !lastAnimation.isClassBased) : |
| | | false; |
| | | |
| | | //skip the animation if animations are disabled, a parent is already being animated, |
| | | //the element is not currently attached to the document body or then completely close |
| | | //the animation if any matching animations are not found at all. |
| | | //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found. |
| | | if (skipAnimations || animationsDisabled(element, parentElement)) { |
| | | fireDOMOperation(); |
| | | fireBeforeCallbackAsync(); |
| | | fireAfterCallbackAsync(); |
| | | closeAnimation(); |
| | | return; |
| | | } |
| | | |
| | | var skipAnimation = false; |
| | | if(totalActiveAnimations > 0) { |
| | | var animationsToCancel = []; |
| | | if(!runner.isClassBased) { |
| | | if(animationEvent == 'leave' && runningAnimations['ng-leave']) { |
| | | skipAnimation = true; |
| | | } else { |
| | | //cancel all animations when a structural animation takes place |
| | | for(var klass in runningAnimations) { |
| | | animationsToCancel.push(runningAnimations[klass]); |
| | | cleanup(element, klass); |
| | | } |
| | | runningAnimations = {}; |
| | | totalActiveAnimations = 0; |
| | | } |
| | | } else if(lastAnimation.event == 'setClass') { |
| | | animationsToCancel.push(lastAnimation); |
| | | cleanup(element, className); |
| | | } |
| | | else if(runningAnimations[className]) { |
| | | var current = runningAnimations[className]; |
| | | if(current.event == animationEvent) { |
| | | skipAnimation = true; |
| | | } else { |
| | | animationsToCancel.push(current); |
| | | cleanup(element, className); |
| | | } |
| | | } |
| | | |
| | | if(animationsToCancel.length > 0) { |
| | | forEach(animationsToCancel, function(operation) { |
| | | operation.cancel(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | if(runner.isClassBased && !runner.isSetClassOperation && !skipAnimation) { |
| | | skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR |
| | | } |
| | | |
| | | if(skipAnimation) { |
| | | fireDOMOperation(); |
| | | fireBeforeCallbackAsync(); |
| | | fireAfterCallbackAsync(); |
| | | fireDoneCallbackAsync(); |
| | | return; |
| | | } |
| | | |
| | | if(animationEvent == 'leave') { |
| | | //there's no need to ever remove the listener since the element |
| | | //will be removed (destroyed) after the leave animation ends or |
| | | //is cancelled midway |
| | | element.one('$destroy', function(e) { |
| | | var element = angular.element(this); |
| | | var state = element.data(NG_ANIMATE_STATE); |
| | | if(state) { |
| | | var activeLeaveAnimation = state.active['ng-leave']; |
| | | if(activeLeaveAnimation) { |
| | | activeLeaveAnimation.cancel(); |
| | | cleanup(element, 'ng-leave'); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | //the ng-animate class does nothing, but it's here to allow for |
| | | //parent animations to find and cancel child animations when needed |
| | | element.addClass(NG_ANIMATE_CLASS_NAME); |
| | | |
| | | var localAnimationCount = globalAnimationCounter++; |
| | | totalActiveAnimations++; |
| | | runningAnimations[className] = runner; |
| | | |
| | | element.data(NG_ANIMATE_STATE, { |
| | | last : runner, |
| | | active : runningAnimations, |
| | | index : localAnimationCount, |
| | | totalActive : totalActiveAnimations |
| | | }); |
| | | |
| | | //first we run the before animations and when all of those are complete |
| | | //then we perform the DOM operation and run the next set of animations |
| | | fireBeforeCallbackAsync(); |
| | | runner.before(function(cancelled) { |
| | | var data = element.data(NG_ANIMATE_STATE); |
| | | cancelled = cancelled || |
| | | !data || !data.active[className] || |
| | | (runner.isClassBased && data.active[className].event != animationEvent); |
| | | |
| | | fireDOMOperation(); |
| | | if(cancelled === true) { |
| | | closeAnimation(); |
| | | } else { |
| | | fireAfterCallbackAsync(); |
| | | runner.after(closeAnimation); |
| | | } |
| | | }); |
| | | |
| | | function fireDOMCallback(animationPhase) { |
| | | var eventName = '$animate:' + animationPhase; |
| | | if(elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { |
| | | $$asyncCallback(function() { |
| | | element.triggerHandler(eventName, { |
| | | event : animationEvent, |
| | | className : className |
| | | }); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | function fireBeforeCallbackAsync() { |
| | | fireDOMCallback('before'); |
| | | } |
| | | |
| | | function fireAfterCallbackAsync() { |
| | | fireDOMCallback('after'); |
| | | } |
| | | |
| | | function fireDoneCallbackAsync() { |
| | | fireDOMCallback('close'); |
| | | if(doneCallback) { |
| | | $$asyncCallback(function() { |
| | | doneCallback(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | //it is less complicated to use a flag than managing and canceling |
| | | //timeouts containing multiple callbacks. |
| | | function fireDOMOperation() { |
| | | if(!fireDOMOperation.hasBeenRun) { |
| | | fireDOMOperation.hasBeenRun = true; |
| | | domOperation(); |
| | | } |
| | | } |
| | | |
| | | function closeAnimation() { |
| | | if(!closeAnimation.hasBeenRun) { |
| | | closeAnimation.hasBeenRun = true; |
| | | var data = element.data(NG_ANIMATE_STATE); |
| | | if(data) { |
| | | /* only structural animations wait for reflow before removing an |
| | | animation, but class-based animations don't. An example of this |
| | | failing would be when a parent HTML tag has a ng-class attribute |
| | | causing ALL directives below to skip animations during the digest */ |
| | | if(runner && runner.isClassBased) { |
| | | cleanup(element, className); |
| | | } else { |
| | | $$asyncCallback(function() { |
| | | var data = element.data(NG_ANIMATE_STATE) || {}; |
| | | if(localAnimationCount == data.index) { |
| | | cleanup(element, className, animationEvent); |
| | | } |
| | | }); |
| | | element.data(NG_ANIMATE_STATE, data); |
| | | } |
| | | } |
| | | fireDoneCallbackAsync(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function cancelChildAnimations(element) { |
| | | var node = extractElementNode(element); |
| | | if (node) { |
| | | var nodes = angular.isFunction(node.getElementsByClassName) ? |
| | | node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) : |
| | | node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME); |
| | | forEach(nodes, function(element) { |
| | | element = angular.element(element); |
| | | var data = element.data(NG_ANIMATE_STATE); |
| | | if(data && data.active) { |
| | | forEach(data.active, function(runner) { |
| | | runner.cancel(); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | function cleanup(element, className) { |
| | | if(isMatchingElement(element, $rootElement)) { |
| | | if(!rootAnimateState.disabled) { |
| | | rootAnimateState.running = false; |
| | | rootAnimateState.structural = false; |
| | | } |
| | | } else if(className) { |
| | | var data = element.data(NG_ANIMATE_STATE) || {}; |
| | | |
| | | var removeAnimations = className === true; |
| | | if(!removeAnimations && data.active && data.active[className]) { |
| | | data.totalActive--; |
| | | delete data.active[className]; |
| | | } |
| | | |
| | | if(removeAnimations || !data.totalActive) { |
| | | element.removeClass(NG_ANIMATE_CLASS_NAME); |
| | | element.removeData(NG_ANIMATE_STATE); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function animationsDisabled(element, parentElement) { |
| | | if (rootAnimateState.disabled) return true; |
| | | |
| | | if(isMatchingElement(element, $rootElement)) { |
| | | return rootAnimateState.disabled || rootAnimateState.running; |
| | | } |
| | | |
| | | do { |
| | | //the element did not reach the root element which means that it |
| | | //is not apart of the DOM. Therefore there is no reason to do |
| | | //any animations on it |
| | | if(parentElement.length === 0) break; |
| | | |
| | | var isRoot = isMatchingElement(parentElement, $rootElement); |
| | | var state = isRoot ? rootAnimateState : parentElement.data(NG_ANIMATE_STATE); |
| | | var result = state && (!!state.disabled || state.running || state.totalActive > 0); |
| | | if(isRoot || result) { |
| | | return result; |
| | | } |
| | | |
| | | if(isRoot) return true; |
| | | } |
| | | while(parentElement = parentElement.parent()); |
| | | |
| | | return true; |
| | | } |
| | | }]); |
| | | |
| | | $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow', |
| | | function($window, $sniffer, $timeout, $$animateReflow) { |
| | | // Detect proper transitionend/animationend event names. |
| | | var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; |
| | | |
| | | // If unprefixed events are not supported but webkit-prefixed are, use the latter. |
| | | // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. |
| | | // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` |
| | | // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. |
| | | // Register both events in case `window.onanimationend` is not supported because of that, |
| | | // do the same for `transitionend` as Safari is likely to exhibit similar behavior. |
| | | // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit |
| | | // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition |
| | | if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { |
| | | CSS_PREFIX = '-webkit-'; |
| | | TRANSITION_PROP = 'WebkitTransition'; |
| | | TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; |
| | | } else { |
| | | TRANSITION_PROP = 'transition'; |
| | | TRANSITIONEND_EVENT = 'transitionend'; |
| | | } |
| | | |
| | | if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { |
| | | CSS_PREFIX = '-webkit-'; |
| | | ANIMATION_PROP = 'WebkitAnimation'; |
| | | ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; |
| | | } else { |
| | | ANIMATION_PROP = 'animation'; |
| | | ANIMATIONEND_EVENT = 'animationend'; |
| | | } |
| | | |
| | | var DURATION_KEY = 'Duration'; |
| | | var PROPERTY_KEY = 'Property'; |
| | | var DELAY_KEY = 'Delay'; |
| | | var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; |
| | | var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; |
| | | var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; |
| | | var NG_ANIMATE_BLOCK_CLASS_NAME = 'ng-animate-block-transitions'; |
| | | var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; |
| | | var CLOSING_TIME_BUFFER = 1.5; |
| | | var ONE_SECOND = 1000; |
| | | |
| | | var lookupCache = {}; |
| | | var parentCounter = 0; |
| | | var animationReflowQueue = []; |
| | | var cancelAnimationReflow; |
| | | function afterReflow(element, callback) { |
| | | if(cancelAnimationReflow) { |
| | | cancelAnimationReflow(); |
| | | } |
| | | animationReflowQueue.push(callback); |
| | | cancelAnimationReflow = $$animateReflow(function() { |
| | | forEach(animationReflowQueue, function(fn) { |
| | | fn(); |
| | | }); |
| | | |
| | | animationReflowQueue = []; |
| | | cancelAnimationReflow = null; |
| | | lookupCache = {}; |
| | | }); |
| | | } |
| | | |
| | | var closingTimer = null; |
| | | var closingTimestamp = 0; |
| | | var animationElementQueue = []; |
| | | function animationCloseHandler(element, totalTime) { |
| | | var node = extractElementNode(element); |
| | | element = angular.element(node); |
| | | |
| | | //this item will be garbage collected by the closing |
| | | //animation timeout |
| | | animationElementQueue.push(element); |
| | | |
| | | //but it may not need to cancel out the existing timeout |
| | | //if the timestamp is less than the previous one |
| | | var futureTimestamp = Date.now() + totalTime; |
| | | if(futureTimestamp <= closingTimestamp) { |
| | | return; |
| | | } |
| | | |
| | | $timeout.cancel(closingTimer); |
| | | |
| | | closingTimestamp = futureTimestamp; |
| | | closingTimer = $timeout(function() { |
| | | closeAllAnimations(animationElementQueue); |
| | | animationElementQueue = []; |
| | | }, totalTime, false); |
| | | } |
| | | |
| | | function closeAllAnimations(elements) { |
| | | forEach(elements, function(element) { |
| | | var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); |
| | | if(elementData) { |
| | | (elementData.closeAnimationFn || noop)(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function getElementAnimationDetails(element, cacheKey) { |
| | | var data = cacheKey ? lookupCache[cacheKey] : null; |
| | | if(!data) { |
| | | var transitionDuration = 0; |
| | | var transitionDelay = 0; |
| | | var animationDuration = 0; |
| | | var animationDelay = 0; |
| | | var transitionDelayStyle; |
| | | var animationDelayStyle; |
| | | var transitionDurationStyle; |
| | | var transitionPropertyStyle; |
| | | |
| | | //we want all the styles defined before and after |
| | | forEach(element, function(element) { |
| | | if (element.nodeType == ELEMENT_NODE) { |
| | | var elementStyles = $window.getComputedStyle(element) || {}; |
| | | |
| | | transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY]; |
| | | |
| | | transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration); |
| | | |
| | | transitionPropertyStyle = elementStyles[TRANSITION_PROP + PROPERTY_KEY]; |
| | | |
| | | transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY]; |
| | | |
| | | transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay); |
| | | |
| | | animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY]; |
| | | |
| | | animationDelay = Math.max(parseMaxTime(animationDelayStyle), animationDelay); |
| | | |
| | | var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]); |
| | | |
| | | if(aDuration > 0) { |
| | | aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1; |
| | | } |
| | | |
| | | animationDuration = Math.max(aDuration, animationDuration); |
| | | } |
| | | }); |
| | | data = { |
| | | total : 0, |
| | | transitionPropertyStyle: transitionPropertyStyle, |
| | | transitionDurationStyle: transitionDurationStyle, |
| | | transitionDelayStyle: transitionDelayStyle, |
| | | transitionDelay: transitionDelay, |
| | | transitionDuration: transitionDuration, |
| | | animationDelayStyle: animationDelayStyle, |
| | | animationDelay: animationDelay, |
| | | animationDuration: animationDuration |
| | | }; |
| | | if(cacheKey) { |
| | | lookupCache[cacheKey] = data; |
| | | } |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | function parseMaxTime(str) { |
| | | var maxValue = 0; |
| | | var values = angular.isString(str) ? |
| | | str.split(/\s*,\s*/) : |
| | | []; |
| | | forEach(values, function(value) { |
| | | maxValue = Math.max(parseFloat(value) || 0, maxValue); |
| | | }); |
| | | return maxValue; |
| | | } |
| | | |
| | | function getCacheKey(element) { |
| | | var parentElement = element.parent(); |
| | | var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY); |
| | | if(!parentID) { |
| | | parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter); |
| | | parentID = parentCounter; |
| | | } |
| | | return parentID + '-' + extractElementNode(element).getAttribute('class'); |
| | | } |
| | | |
| | | function animateSetup(animationEvent, element, className, calculationDecorator) { |
| | | var cacheKey = getCacheKey(element); |
| | | var eventCacheKey = cacheKey + ' ' + className; |
| | | var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; |
| | | |
| | | var stagger = {}; |
| | | if(itemIndex > 0) { |
| | | var staggerClassName = className + '-stagger'; |
| | | var staggerCacheKey = cacheKey + ' ' + staggerClassName; |
| | | var applyClasses = !lookupCache[staggerCacheKey]; |
| | | |
| | | applyClasses && element.addClass(staggerClassName); |
| | | |
| | | stagger = getElementAnimationDetails(element, staggerCacheKey); |
| | | |
| | | applyClasses && element.removeClass(staggerClassName); |
| | | } |
| | | |
| | | /* the animation itself may need to add/remove special CSS classes |
| | | * before calculating the anmation styles */ |
| | | calculationDecorator = calculationDecorator || |
| | | function(fn) { return fn(); }; |
| | | |
| | | element.addClass(className); |
| | | |
| | | var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {}; |
| | | |
| | | var timings = calculationDecorator(function() { |
| | | return getElementAnimationDetails(element, eventCacheKey); |
| | | }); |
| | | |
| | | var transitionDuration = timings.transitionDuration; |
| | | var animationDuration = timings.animationDuration; |
| | | if(transitionDuration === 0 && animationDuration === 0) { |
| | | element.removeClass(className); |
| | | return false; |
| | | } |
| | | |
| | | element.data(NG_ANIMATE_CSS_DATA_KEY, { |
| | | running : formerData.running || 0, |
| | | itemIndex : itemIndex, |
| | | stagger : stagger, |
| | | timings : timings, |
| | | closeAnimationFn : noop |
| | | }); |
| | | |
| | | //temporarily disable the transition so that the enter styles |
| | | //don't animate twice (this is here to avoid a bug in Chrome/FF). |
| | | var isCurrentlyAnimating = formerData.running > 0 || animationEvent == 'setClass'; |
| | | if(transitionDuration > 0) { |
| | | blockTransitions(element, className, isCurrentlyAnimating); |
| | | } |
| | | |
| | | //staggering keyframe animations work by adjusting the `animation-delay` CSS property |
| | | //on the given element, however, the delay value can only calculated after the reflow |
| | | //since by that time $animate knows how many elements are being animated. Therefore, |
| | | //until the reflow occurs the element needs to be blocked (where the keyframe animation |
| | | //is set to `none 0s`). This blocking mechanism should only be set for when a stagger |
| | | //animation is detected and when the element item index is greater than 0. |
| | | if(animationDuration > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0) { |
| | | blockKeyframeAnimations(element); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | function isStructuralAnimation(className) { |
| | | return className == 'ng-enter' || className == 'ng-move' || className == 'ng-leave'; |
| | | } |
| | | |
| | | function blockTransitions(element, className, isAnimating) { |
| | | if(isStructuralAnimation(className) || !isAnimating) { |
| | | extractElementNode(element).style[TRANSITION_PROP + PROPERTY_KEY] = 'none'; |
| | | } else { |
| | | element.addClass(NG_ANIMATE_BLOCK_CLASS_NAME); |
| | | } |
| | | } |
| | | |
| | | function blockKeyframeAnimations(element) { |
| | | extractElementNode(element).style[ANIMATION_PROP] = 'none 0s'; |
| | | } |
| | | |
| | | function unblockTransitions(element, className) { |
| | | var prop = TRANSITION_PROP + PROPERTY_KEY; |
| | | var node = extractElementNode(element); |
| | | if(node.style[prop] && node.style[prop].length > 0) { |
| | | node.style[prop] = ''; |
| | | } |
| | | element.removeClass(NG_ANIMATE_BLOCK_CLASS_NAME); |
| | | } |
| | | |
| | | function unblockKeyframeAnimations(element) { |
| | | var prop = ANIMATION_PROP; |
| | | var node = extractElementNode(element); |
| | | if(node.style[prop] && node.style[prop].length > 0) { |
| | | node.style[prop] = ''; |
| | | } |
| | | } |
| | | |
| | | function animateRun(animationEvent, element, className, activeAnimationComplete) { |
| | | var node = extractElementNode(element); |
| | | var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); |
| | | if(node.getAttribute('class').indexOf(className) == -1 || !elementData) { |
| | | activeAnimationComplete(); |
| | | return; |
| | | } |
| | | |
| | | var activeClassName = ''; |
| | | forEach(className.split(' '), function(klass, i) { |
| | | activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; |
| | | }); |
| | | |
| | | var stagger = elementData.stagger; |
| | | var timings = elementData.timings; |
| | | var itemIndex = elementData.itemIndex; |
| | | var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); |
| | | var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); |
| | | var maxDelayTime = maxDelay * ONE_SECOND; |
| | | |
| | | var startTime = Date.now(); |
| | | var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; |
| | | |
| | | var style = '', appliedStyles = []; |
| | | if(timings.transitionDuration > 0) { |
| | | var propertyStyle = timings.transitionPropertyStyle; |
| | | if(propertyStyle.indexOf('all') == -1) { |
| | | style += CSS_PREFIX + 'transition-property: ' + propertyStyle + ';'; |
| | | style += CSS_PREFIX + 'transition-duration: ' + timings.transitionDurationStyle + ';'; |
| | | appliedStyles.push(CSS_PREFIX + 'transition-property'); |
| | | appliedStyles.push(CSS_PREFIX + 'transition-duration'); |
| | | } |
| | | } |
| | | |
| | | if(itemIndex > 0) { |
| | | if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { |
| | | var delayStyle = timings.transitionDelayStyle; |
| | | style += CSS_PREFIX + 'transition-delay: ' + |
| | | prepareStaggerDelay(delayStyle, stagger.transitionDelay, itemIndex) + '; '; |
| | | appliedStyles.push(CSS_PREFIX + 'transition-delay'); |
| | | } |
| | | |
| | | if(stagger.animationDelay > 0 && stagger.animationDuration === 0) { |
| | | style += CSS_PREFIX + 'animation-delay: ' + |
| | | prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, itemIndex) + '; '; |
| | | appliedStyles.push(CSS_PREFIX + 'animation-delay'); |
| | | } |
| | | } |
| | | |
| | | if(appliedStyles.length > 0) { |
| | | //the element being animated may sometimes contain comment nodes in |
| | | //the jqLite object, so we're safe to use a single variable to house |
| | | //the styles since there is always only one element being animated |
| | | var oldStyle = node.getAttribute('style') || ''; |
| | | node.setAttribute('style', oldStyle + '; ' + style); |
| | | } |
| | | |
| | | element.on(css3AnimationEvents, onAnimationProgress); |
| | | element.addClass(activeClassName); |
| | | elementData.closeAnimationFn = function() { |
| | | onEnd(); |
| | | activeAnimationComplete(); |
| | | }; |
| | | |
| | | var staggerTime = itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0); |
| | | var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER; |
| | | var totalTime = (staggerTime + animationTime) * ONE_SECOND; |
| | | |
| | | elementData.running++; |
| | | animationCloseHandler(element, totalTime); |
| | | return onEnd; |
| | | |
| | | // This will automatically be called by $animate so |
| | | // there is no need to attach this internally to the |
| | | // timeout done method. |
| | | function onEnd(cancelled) { |
| | | element.off(css3AnimationEvents, onAnimationProgress); |
| | | element.removeClass(activeClassName); |
| | | animateClose(element, className); |
| | | var node = extractElementNode(element); |
| | | for (var i in appliedStyles) { |
| | | node.style.removeProperty(appliedStyles[i]); |
| | | } |
| | | } |
| | | |
| | | function onAnimationProgress(event) { |
| | | event.stopPropagation(); |
| | | var ev = event.originalEvent || event; |
| | | var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); |
| | | |
| | | /* Firefox (or possibly just Gecko) likes to not round values up |
| | | * when a ms measurement is used for the animation */ |
| | | var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); |
| | | |
| | | /* $manualTimeStamp is a mocked timeStamp value which is set |
| | | * within browserTrigger(). This is only here so that tests can |
| | | * mock animations properly. Real events fallback to event.timeStamp, |
| | | * or, if they don't, then a timeStamp is automatically created for them. |
| | | * We're checking to see if the timeStamp surpasses the expected delay, |
| | | * but we're using elapsedTime instead of the timeStamp on the 2nd |
| | | * pre-condition since animations sometimes close off early */ |
| | | if(Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { |
| | | activeAnimationComplete(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function prepareStaggerDelay(delayStyle, staggerDelay, index) { |
| | | var style = ''; |
| | | forEach(delayStyle.split(','), function(val, i) { |
| | | style += (i > 0 ? ',' : '') + |
| | | (index * staggerDelay + parseInt(val, 10)) + 's'; |
| | | }); |
| | | return style; |
| | | } |
| | | |
| | | function animateBefore(animationEvent, element, className, calculationDecorator) { |
| | | if(animateSetup(animationEvent, element, className, calculationDecorator)) { |
| | | return function(cancelled) { |
| | | cancelled && animateClose(element, className); |
| | | }; |
| | | } |
| | | } |
| | | |
| | | function animateAfter(animationEvent, element, className, afterAnimationComplete) { |
| | | if(element.data(NG_ANIMATE_CSS_DATA_KEY)) { |
| | | return animateRun(animationEvent, element, className, afterAnimationComplete); |
| | | } else { |
| | | animateClose(element, className); |
| | | afterAnimationComplete(); |
| | | } |
| | | } |
| | | |
| | | function animate(animationEvent, element, className, animationComplete) { |
| | | //If the animateSetup function doesn't bother returning a |
| | | //cancellation function then it means that there is no animation |
| | | //to perform at all |
| | | var preReflowCancellation = animateBefore(animationEvent, element, className); |
| | | if(!preReflowCancellation) { |
| | | animationComplete(); |
| | | return; |
| | | } |
| | | |
| | | //There are two cancellation functions: one is before the first |
| | | //reflow animation and the second is during the active state |
| | | //animation. The first function will take care of removing the |
| | | //data from the element which will not make the 2nd animation |
| | | //happen in the first place |
| | | var cancel = preReflowCancellation; |
| | | afterReflow(element, function() { |
| | | unblockTransitions(element, className); |
| | | unblockKeyframeAnimations(element); |
| | | //once the reflow is complete then we point cancel to |
| | | //the new cancellation function which will remove all of the |
| | | //animation properties from the active animation |
| | | cancel = animateAfter(animationEvent, element, className, animationComplete); |
| | | }); |
| | | |
| | | return function(cancelled) { |
| | | (cancel || noop)(cancelled); |
| | | }; |
| | | } |
| | | |
| | | function animateClose(element, className) { |
| | | element.removeClass(className); |
| | | var data = element.data(NG_ANIMATE_CSS_DATA_KEY); |
| | | if(data) { |
| | | if(data.running) { |
| | | data.running--; |
| | | } |
| | | if(!data.running || data.running === 0) { |
| | | element.removeData(NG_ANIMATE_CSS_DATA_KEY); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return { |
| | | enter : function(element, animationCompleted) { |
| | | return animate('enter', element, 'ng-enter', animationCompleted); |
| | | }, |
| | | |
| | | leave : function(element, animationCompleted) { |
| | | return animate('leave', element, 'ng-leave', animationCompleted); |
| | | }, |
| | | |
| | | move : function(element, animationCompleted) { |
| | | return animate('move', element, 'ng-move', animationCompleted); |
| | | }, |
| | | |
| | | beforeSetClass : function(element, add, remove, animationCompleted) { |
| | | var className = suffixClasses(remove, '-remove') + ' ' + |
| | | suffixClasses(add, '-add'); |
| | | var cancellationMethod = animateBefore('setClass', element, className, function(fn) { |
| | | /* when classes are removed from an element then the transition style |
| | | * that is applied is the transition defined on the element without the |
| | | * CSS class being there. This is how CSS3 functions outside of ngAnimate. |
| | | * http://plnkr.co/edit/j8OzgTNxHTb4n3zLyjGW?p=preview */ |
| | | var klass = element.attr('class'); |
| | | element.removeClass(remove); |
| | | element.addClass(add); |
| | | var timings = fn(); |
| | | element.attr('class', klass); |
| | | return timings; |
| | | }); |
| | | |
| | | if(cancellationMethod) { |
| | | afterReflow(element, function() { |
| | | unblockTransitions(element, className); |
| | | unblockKeyframeAnimations(element); |
| | | animationCompleted(); |
| | | }); |
| | | return cancellationMethod; |
| | | } |
| | | animationCompleted(); |
| | | }, |
| | | |
| | | beforeAddClass : function(element, className, animationCompleted) { |
| | | var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), function(fn) { |
| | | |
| | | /* when a CSS class is added to an element then the transition style that |
| | | * is applied is the transition defined on the element when the CSS class |
| | | * is added at the time of the animation. This is how CSS3 functions |
| | | * outside of ngAnimate. */ |
| | | element.addClass(className); |
| | | var timings = fn(); |
| | | element.removeClass(className); |
| | | return timings; |
| | | }); |
| | | |
| | | if(cancellationMethod) { |
| | | afterReflow(element, function() { |
| | | unblockTransitions(element, className); |
| | | unblockKeyframeAnimations(element); |
| | | animationCompleted(); |
| | | }); |
| | | return cancellationMethod; |
| | | } |
| | | animationCompleted(); |
| | | }, |
| | | |
| | | setClass : function(element, add, remove, animationCompleted) { |
| | | remove = suffixClasses(remove, '-remove'); |
| | | add = suffixClasses(add, '-add'); |
| | | var className = remove + ' ' + add; |
| | | return animateAfter('setClass', element, className, animationCompleted); |
| | | }, |
| | | |
| | | addClass : function(element, className, animationCompleted) { |
| | | return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted); |
| | | }, |
| | | |
| | | beforeRemoveClass : function(element, className, animationCompleted) { |
| | | var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), function(fn) { |
| | | /* when classes are removed from an element then the transition style |
| | | * that is applied is the transition defined on the element without the |
| | | * CSS class being there. This is how CSS3 functions outside of ngAnimate. |
| | | * http://plnkr.co/edit/j8OzgTNxHTb4n3zLyjGW?p=preview */ |
| | | var klass = element.attr('class'); |
| | | element.removeClass(className); |
| | | var timings = fn(); |
| | | element.attr('class', klass); |
| | | return timings; |
| | | }); |
| | | |
| | | if(cancellationMethod) { |
| | | afterReflow(element, function() { |
| | | unblockTransitions(element, className); |
| | | unblockKeyframeAnimations(element); |
| | | animationCompleted(); |
| | | }); |
| | | return cancellationMethod; |
| | | } |
| | | animationCompleted(); |
| | | }, |
| | | |
| | | removeClass : function(element, className, animationCompleted) { |
| | | return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted); |
| | | } |
| | | }; |
| | | |
| | | function suffixClasses(classes, suffix) { |
| | | var className = ''; |
| | | classes = angular.isArray(classes) ? classes : classes.split(/\s+/); |
| | | forEach(classes, function(klass, i) { |
| | | if(klass && klass.length > 0) { |
| | | className += (i > 0 ? ' ' : '') + klass + suffix; |
| | | } |
| | | }); |
| | | return className; |
| | | } |
| | | }]); |
| | | }]); |
| | | |
| | | |
| | | })(window, window.angular); |
New file |
| | |
| | | /* |
| | | AngularJS v1.2.18 |
| | | (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | License: MIT |
| | | */ |
| | | (function(u,f,P){'use strict';f.module("ngAnimate",["ng"]).factory("$$animateReflow",["$$rAF","$document",function(f,u){return function(e){return f(function(){e()})}}]).config(["$provide","$animateProvider",function(W,H){function e(f){for(var e=0;e<f.length;e++){var h=f[e];if(h.nodeType==aa)return h}}function C(h){return f.element(e(h))}var n=f.noop,h=f.forEach,Q=H.$$selectors,aa=1,k="$$ngAnimateState",K="ng-animate",g={running:!0};W.decorator("$animate",["$delegate","$injector","$sniffer","$rootElement", |
| | | "$$asyncCallback","$rootScope","$document",function(y,u,$,L,F,I,P){function R(a){if(a){var b=[],c={};a=a.substr(1).split(".");($.transitions||$.animations)&&b.push(u.get(Q[""]));for(var d=0;d<a.length;d++){var f=a[d],e=Q[f];e&&!c[f]&&(b.push(u.get(e)),c[f]=!0)}return b}}function M(a,b,c){function d(a,b){var c=a[b],d=a["before"+b.charAt(0).toUpperCase()+b.substr(1)];if(c||d)return"leave"==b&&(d=c,c=null),t.push({event:b,fn:c}),l.push({event:b,fn:d}),!0}function e(b,d,f){var q=[];h(b,function(a){a.fn&& |
| | | q.push(a)});var m=0;h(q,function(b,e){var h=function(){a:{if(d){(d[e]||n)();if(++m<q.length)break a;d=null}f()}};switch(b.event){case "setClass":d.push(b.fn(a,p,A,h));break;case "addClass":d.push(b.fn(a,p||c,h));break;case "removeClass":d.push(b.fn(a,A||c,h));break;default:d.push(b.fn(a,h))}});d&&0===d.length&&f()}var w=a[0];if(w){var k="setClass"==b,g=k||"addClass"==b||"removeClass"==b,p,A;f.isArray(c)&&(p=c[0],A=c[1],c=p+" "+A);var B=a.attr("class")+" "+c;if(T(B)){var r=n,v=[],l=[],x=n,m=[],t=[], |
| | | B=(" "+B).replace(/\s+/g,".");h(R(B),function(a){!d(a,b)&&k&&(d(a,"addClass"),d(a,"removeClass"))});return{node:w,event:b,className:c,isClassBased:g,isSetClassOperation:k,before:function(a){r=a;e(l,v,function(){r=n;a()})},after:function(a){x=a;e(t,m,function(){x=n;a()})},cancel:function(){v&&(h(v,function(a){(a||n)(!0)}),r(!0));m&&(h(m,function(a){(a||n)(!0)}),x(!0))}}}}}function z(a,b,c,d,e,w,g){function n(d){var e="$animate:"+d;x&&(x[e]&&0<x[e].length)&&F(function(){c.triggerHandler(e,{event:a, |
| | | className:b})})}function p(){n("before")}function A(){n("after")}function B(){n("close");g&&F(function(){g()})}function r(){r.hasBeenRun||(r.hasBeenRun=!0,w())}function v(){if(!v.hasBeenRun){v.hasBeenRun=!0;var d=c.data(k);d&&(l&&l.isClassBased?D(c,b):(F(function(){var d=c.data(k)||{};z==d.index&&D(c,b,a)}),c.data(k,d)));B()}}var l=M(c,a,b);if(l){b=l.className;var x=f.element._data(l.node),x=x&&x.events;d||(d=e?e.parent():c.parent());var m=c.data(k)||{};e=m.active||{};var t=m.totalActive||0,u=m.last; |
| | | if(l.isClassBased&&(m.disabled||u&&!u.isClassBased)||N(c,d))r(),p(),A(),v();else{d=!1;if(0<t){m=[];if(l.isClassBased)"setClass"==u.event?(m.push(u),D(c,b)):e[b]&&(y=e[b],y.event==a?d=!0:(m.push(y),D(c,b)));else if("leave"==a&&e["ng-leave"])d=!0;else{for(var y in e)m.push(e[y]),D(c,y);e={};t=0}0<m.length&&h(m,function(a){a.cancel()})}!l.isClassBased||(l.isSetClassOperation||d)||(d="addClass"==a==c.hasClass(b));if(d)r(),p(),A(),B();else{if("leave"==a)c.one("$destroy",function(a){a=f.element(this);var b= |
| | | a.data(k);b&&(b=b.active["ng-leave"])&&(b.cancel(),D(a,"ng-leave"))});c.addClass(K);var z=O++;t++;e[b]=l;c.data(k,{last:l,active:e,index:z,totalActive:t});p();l.before(function(d){var e=c.data(k);d=d||!e||!e.active[b]||l.isClassBased&&e.active[b].event!=a;r();!0===d?v():(A(),l.after(v))})}}}else r(),p(),A(),v()}function U(a){if(a=e(a))a=f.isFunction(a.getElementsByClassName)?a.getElementsByClassName(K):a.querySelectorAll("."+K),h(a,function(a){a=f.element(a);(a=a.data(k))&&a.active&&h(a.active,function(a){a.cancel()})})} |
| | | function D(a,b){if(e(a)==e(L))g.disabled||(g.running=!1,g.structural=!1);else if(b){var c=a.data(k)||{},d=!0===b;!d&&(c.active&&c.active[b])&&(c.totalActive--,delete c.active[b]);if(d||!c.totalActive)a.removeClass(K),a.removeData(k)}}function N(a,b){if(g.disabled)return!0;if(e(a)==e(L))return g.disabled||g.running;do{if(0===b.length)break;var c=e(b)==e(L),d=c?g:b.data(k),d=d&&(!!d.disabled||d.running||0<d.totalActive);if(c||d)return d;if(c)break}while(b=b.parent());return!0}var O=0;L.data(k,g);I.$$postDigest(function(){I.$$postDigest(function(){g.running= |
| | | !1})});var V=H.classNameFilter(),T=V?function(a){return V.test(a)}:function(){return!0};return{enter:function(a,b,c,d){a=f.element(a);b=b&&f.element(b);c=c&&f.element(c);this.enabled(!1,a);y.enter(a,b,c);I.$$postDigest(function(){a=C(a);z("enter","ng-enter",a,b,c,n,d)})},leave:function(a,b){a=f.element(a);U(a);this.enabled(!1,a);I.$$postDigest(function(){z("leave","ng-leave",C(a),null,null,function(){y.leave(a)},b)})},move:function(a,b,c,d){a=f.element(a);b=b&&f.element(b);c=c&&f.element(c);U(a); |
| | | this.enabled(!1,a);y.move(a,b,c);I.$$postDigest(function(){a=C(a);z("move","ng-move",a,b,c,n,d)})},addClass:function(a,b,c){a=f.element(a);a=C(a);z("addClass",b,a,null,null,function(){y.addClass(a,b)},c)},removeClass:function(a,b,c){a=f.element(a);a=C(a);z("removeClass",b,a,null,null,function(){y.removeClass(a,b)},c)},setClass:function(a,b,c,d){a=f.element(a);a=C(a);z("setClass",[b,c],a,null,null,function(){y.setClass(a,b,c)},d)},enabled:function(a,b){switch(arguments.length){case 2:if(a)D(b);else{var c= |
| | | b.data(k)||{};c.disabled=!0;b.data(k,c)}break;case 1:g.disabled=!a;break;default:a=!g.disabled}return!!a}}}]);H.register("",["$window","$sniffer","$timeout","$$animateReflow",function(k,g,C,L){function F(a,E){S&&S();X.push(E);S=L(function(){h(X,function(a){a()});X=[];S=null;q={}})}function I(a,E){var b=e(a);a=f.element(b);Y.push(a);b=Date.now()+E;b<=ea||(C.cancel(da),ea=b,da=C(function(){K(Y);Y=[]},E,!1))}function K(a){h(a,function(a){(a=a.data(m))&&(a.closeAnimationFn||n)()})}function R(a,E){var b= |
| | | E?q[E]:null;if(!b){var c=0,d=0,e=0,f=0,m,Z,s,g;h(a,function(a){if(a.nodeType==aa){a=k.getComputedStyle(a)||{};s=a[J+B];c=Math.max(M(s),c);g=a[J+r];m=a[J+v];d=Math.max(M(m),d);Z=a[p+v];f=Math.max(M(Z),f);var b=M(a[p+B]);0<b&&(b*=parseInt(a[p+l],10)||1);e=Math.max(b,e)}});b={total:0,transitionPropertyStyle:g,transitionDurationStyle:s,transitionDelayStyle:m,transitionDelay:d,transitionDuration:c,animationDelayStyle:Z,animationDelay:f,animationDuration:e};E&&(q[E]=b)}return b}function M(a){var b=0;a= |
| | | f.isString(a)?a.split(/\s*,\s*/):[];h(a,function(a){b=Math.max(parseFloat(a)||0,b)});return b}function z(a){var b=a.parent(),c=b.data(x);c||(b.data(x,++ca),c=ca);return c+"-"+e(a).getAttribute("class")}function U(a,b,c,d){var f=z(b),h=f+" "+c,k=q[h]?++q[h].total:0,g={};if(0<k){var l=c+"-stagger",g=f+" "+l;(f=!q[g])&&b.addClass(l);g=R(b,g);f&&b.removeClass(l)}d=d||function(a){return a()};b.addClass(c);var l=b.data(m)||{},s=d(function(){return R(b,h)});d=s.transitionDuration;f=s.animationDuration;if(0=== |
| | | d&&0===f)return b.removeClass(c),!1;b.data(m,{running:l.running||0,itemIndex:k,stagger:g,timings:s,closeAnimationFn:n});a=0<l.running||"setClass"==a;0<d&&D(b,c,a);0<f&&(0<g.animationDelay&&0===g.animationDuration)&&(e(b).style[p]="none 0s");return!0}function D(a,b,c){"ng-enter"!=b&&("ng-move"!=b&&"ng-leave"!=b)&&c?a.addClass(t):e(a).style[J+r]="none"}function N(a,b){var c=J+r,d=e(a);d.style[c]&&0<d.style[c].length&&(d.style[c]="");a.removeClass(t)}function O(a){var b=p;a=e(a);a.style[b]&&0<a.style[b].length&& |
| | | (a.style[b]="")}function V(a,b,c,f){function g(a){b.off(z,l);b.removeClass(p);d(b,c);a=e(b);for(var fa in t)a.style.removeProperty(t[fa])}function l(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(Q));Math.max(a-y,0)>=x&&b>=u&&f()}var k=e(b);a=b.data(m);if(-1!=k.getAttribute("class").indexOf(c)&&a){var p="";h(c.split(" "),function(a,b){p+=(0<b?" ":"")+a+"-active"});var n=a.stagger,s=a.timings,r=a.itemIndex,u=Math.max(s.transitionDuration, |
| | | s.animationDuration),v=Math.max(s.transitionDelay,s.animationDelay),x=v*ba,y=Date.now(),z=A+" "+H,q="",t=[];if(0<s.transitionDuration){var B=s.transitionPropertyStyle;-1==B.indexOf("all")&&(q+=w+"transition-property: "+B+";",q+=w+"transition-duration: "+s.transitionDurationStyle+";",t.push(w+"transition-property"),t.push(w+"transition-duration"))}0<r&&(0<n.transitionDelay&&0===n.transitionDuration&&(q+=w+"transition-delay: "+T(s.transitionDelayStyle,n.transitionDelay,r)+"; ",t.push(w+"transition-delay")), |
| | | 0<n.animationDelay&&0===n.animationDuration&&(q+=w+"animation-delay: "+T(s.animationDelayStyle,n.animationDelay,r)+"; ",t.push(w+"animation-delay")));0<t.length&&(s=k.getAttribute("style")||"",k.setAttribute("style",s+"; "+q));b.on(z,l);b.addClass(p);a.closeAnimationFn=function(){g();f()};k=(r*(Math.max(n.animationDelay,n.transitionDelay)||0)+(v+u)*W)*ba;a.running++;I(b,k);return g}f()}function T(a,b,c){var d="";h(a.split(","),function(a,e){d+=(0<e?",":"")+(c*b+parseInt(a,10))+"s"});return d}function a(a, |
| | | b,c,e){if(U(a,b,c,e))return function(a){a&&d(b,c)}}function b(a,b,c,e){if(b.data(m))return V(a,b,c,e);d(b,c);e()}function c(c,d,e,f){var g=a(c,d,e);if(g){var h=g;F(d,function(){N(d,e);O(d);h=b(c,d,e,f)});return function(a){(h||n)(a)}}f()}function d(a,b){a.removeClass(b);var c=a.data(m);c&&(c.running&&c.running--,c.running&&0!==c.running||a.removeData(m))}function G(a,b){var c="";a=f.isArray(a)?a:a.split(/\s+/);h(a,function(a,d){a&&0<a.length&&(c+=(0<d?" ":"")+a+b)});return c}var w="",J,H,p,A;u.ontransitionend=== |
| | | P&&u.onwebkittransitionend!==P?(w="-webkit-",J="WebkitTransition",H="webkitTransitionEnd transitionend"):(J="transition",H="transitionend");u.onanimationend===P&&u.onwebkitanimationend!==P?(w="-webkit-",p="WebkitAnimation",A="webkitAnimationEnd animationend"):(p="animation",A="animationend");var B="Duration",r="Property",v="Delay",l="IterationCount",x="$$ngAnimateKey",m="$$ngAnimateCSS3Data",t="ng-animate-block-transitions",Q=3,W=1.5,ba=1E3,q={},ca=0,X=[],S,da=null,ea=0,Y=[];return{enter:function(a, |
| | | b){return c("enter",a,"ng-enter",b)},leave:function(a,b){return c("leave",a,"ng-leave",b)},move:function(a,b){return c("move",a,"ng-move",b)},beforeSetClass:function(b,c,d,e){var f=G(d,"-remove")+" "+G(c,"-add"),g=a("setClass",b,f,function(a){var e=b.attr("class");b.removeClass(d);b.addClass(c);a=a();b.attr("class",e);return a});if(g)return F(b,function(){N(b,f);O(b);e()}),g;e()},beforeAddClass:function(b,c,d){var e=a("addClass",b,G(c,"-add"),function(a){b.addClass(c);a=a();b.removeClass(c);return a}); |
| | | if(e)return F(b,function(){N(b,c);O(b);d()}),e;d()},setClass:function(a,c,d,e){d=G(d,"-remove");c=G(c,"-add");return b("setClass",a,d+" "+c,e)},addClass:function(a,c,d){return b("addClass",a,G(c,"-add"),d)},beforeRemoveClass:function(b,c,d){var e=a("removeClass",b,G(c,"-remove"),function(a){var d=b.attr("class");b.removeClass(c);a=a();b.attr("class",d);return a});if(e)return F(b,function(){N(b,c);O(b);d()}),e;d()},removeClass:function(a,c,d){return b("removeClass",a,G(c,"-remove"),d)}}}])}])})(window, |
| | | window.angular); |
| | | //# sourceMappingURL=angular-animate.min.js.map |
New file |
| | |
| | | { |
| | | "version":3, |
| | | "file":"angular-animate.min.js", |
| | | "lineCount":27, |
| | | "mappings":"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", |
| | | "sources":["angular-animate.js"], |
| | | "names":["window","angular","undefined","module","factory","$$rAF","$document","fn","config","$provide","$animateProvider","extractElementNode","element","i","length","elm","nodeType","ELEMENT_NODE","stripCommentsFromElement","noop","forEach","selectors","$$selectors","NG_ANIMATE_STATE","NG_ANIMATE_CLASS_NAME","rootAnimateState","decorator","$delegate","$injector","$sniffer","$rootElement","$$asyncCallback","$rootScope","lookup","name","matches","flagMap","classes","substr","split","transitions","animations","push","get","klass","selectorFactoryName","animationRunner","animationEvent","className","registerAnimation","animationFactory","event","afterFn","beforeFn","charAt","toUpperCase","after","before","run","fns","cancellations","allCompleteFn","animation","count","index","progress","classNameAdd","classNameRemove","node","isSetClassOperation","isClassBased","isArray","attr","currentClassName","isAnimatableClassName","beforeComplete","beforeCancel","afterComplete","afterCancel","animationLookup","replace","created","cancel","cancelFn","performAnimation","parentElement","afterElement","domOperation","doneCallback","fireDOMCallback","animationPhase","eventName","elementEvents","triggerHandler","fireBeforeCallbackAsync","fireAfterCallbackAsync","fireDoneCallbackAsync","fireDOMOperation","hasBeenRun","closeAnimation","data","runner","cleanup","localAnimationCount","_data","events","parent","ngAnimateState","runningAnimations","active","totalActiveAnimations","totalActive","lastAnimation","last","disabled","animationsDisabled","skipAnimation","animationsToCancel","current","operation","hasClass","one","e","state","activeLeaveAnimation","addClass","globalAnimationCounter","cancelled","cancelChildAnimations","nodes","isFunction","getElementsByClassName","querySelectorAll","running","structural","removeAnimations","removeClass","removeData","isRoot","result","$$postDigest","classNameFilter","test","enter","enabled","leave","move","setClass","add","remove","value","arguments","register","$window","$timeout","$$animateReflow","afterReflow","callback","cancelAnimationReflow","animationReflowQueue","lookupCache","animationCloseHandler","totalTime","animationElementQueue","futureTimestamp","Date","now","closingTimestamp","closingTimer","closeAllAnimations","elements","elementData","NG_ANIMATE_CSS_DATA_KEY","closeAnimationFn","getElementAnimationDetails","cacheKey","transitionDuration","transitionDelay","animationDuration","animationDelay","transitionDelayStyle","animationDelayStyle","transitionDurationStyle","transitionPropertyStyle","elementStyles","getComputedStyle","TRANSITION_PROP","DURATION_KEY","Math","max","parseMaxTime","PROPERTY_KEY","DELAY_KEY","ANIMATION_PROP","aDuration","parseInt","ANIMATION_ITERATION_COUNT_KEY","str","maxValue","values","isString","parseFloat","getCacheKey","parentID","NG_ANIMATE_PARENT_KEY","parentCounter","getAttribute","animateSetup","calculationDecorator","eventCacheKey","itemIndex","total","stagger","staggerClassName","staggerCacheKey","applyClasses","formerData","timings","isCurrentlyAnimating","blockTransitions","style","isAnimating","NG_ANIMATE_BLOCK_CLASS_NAME","unblockTransitions","prop","unblockKeyframeAnimations","animateRun","activeAnimationComplete","onEnd","off","css3AnimationEvents","onAnimationProgress","activeClassName","animateClose","appliedStyles","removeProperty","stopPropagation","ev","originalEvent","timeStamp","$manualTimeStamp","elapsedTime","toFixed","ELAPSED_TIME_MAX_DECIMAL_PLACES","startTime","maxDelayTime","maxDuration","indexOf","maxDelay","ONE_SECOND","ANIMATIONEND_EVENT","TRANSITIONEND_EVENT","propertyStyle","CSS_PREFIX","prepareStaggerDelay","oldStyle","setAttribute","on","elementData.closeAnimationFn","CLOSING_TIME_BUFFER","delayStyle","staggerDelay","val","animateBefore","animateAfter","afterAnimationComplete","animate","animationComplete","preReflowCancellation","suffixClasses","suffix","ontransitionend","onwebkittransitionend","onanimationend","onwebkitanimationend","animationCompleted","beforeSetClass","cancellationMethod","beforeAddClass","beforeRemoveClass"] |
| | | } |
New file |
| | |
| | | /** |
| | | * @license AngularJS v1.2.18 |
| | | * (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | * License: MIT |
| | | */ |
| | | (function(window, angular, undefined) {'use strict'; |
| | | |
| | | /** |
| | | * @ngdoc module |
| | | * @name ngCookies |
| | | * @description |
| | | * |
| | | * # ngCookies |
| | | * |
| | | * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies. |
| | | * |
| | | * |
| | | * <div doc-module-components="ngCookies"></div> |
| | | * |
| | | * See {@link ngCookies.$cookies `$cookies`} and |
| | | * {@link ngCookies.$cookieStore `$cookieStore`} for usage. |
| | | */ |
| | | |
| | | |
| | | angular.module('ngCookies', ['ng']). |
| | | /** |
| | | * @ngdoc service |
| | | * @name $cookies |
| | | * |
| | | * @description |
| | | * Provides read/write access to browser's cookies. |
| | | * |
| | | * Only a simple Object is exposed and by adding or removing properties to/from this object, new |
| | | * cookies are created/deleted at the end of current $eval. |
| | | * The object's properties can only be strings. |
| | | * |
| | | * Requires the {@link ngCookies `ngCookies`} module to be installed. |
| | | * |
| | | * @example |
| | | * |
| | | * ```js |
| | | * function ExampleController($cookies) { |
| | | * // Retrieving a cookie |
| | | * var favoriteCookie = $cookies.myFavorite; |
| | | * // Setting a cookie |
| | | * $cookies.myFavorite = 'oatmeal'; |
| | | * } |
| | | * ``` |
| | | */ |
| | | factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) { |
| | | var cookies = {}, |
| | | lastCookies = {}, |
| | | lastBrowserCookies, |
| | | runEval = false, |
| | | copy = angular.copy, |
| | | isUndefined = angular.isUndefined; |
| | | |
| | | //creates a poller fn that copies all cookies from the $browser to service & inits the service |
| | | $browser.addPollFn(function() { |
| | | var currentCookies = $browser.cookies(); |
| | | if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl |
| | | lastBrowserCookies = currentCookies; |
| | | copy(currentCookies, lastCookies); |
| | | copy(currentCookies, cookies); |
| | | if (runEval) $rootScope.$apply(); |
| | | } |
| | | })(); |
| | | |
| | | runEval = true; |
| | | |
| | | //at the end of each eval, push cookies |
| | | //TODO: this should happen before the "delayed" watches fire, because if some cookies are not |
| | | // strings or browser refuses to store some cookies, we update the model in the push fn. |
| | | $rootScope.$watch(push); |
| | | |
| | | return cookies; |
| | | |
| | | |
| | | /** |
| | | * Pushes all the cookies from the service to the browser and verifies if all cookies were |
| | | * stored. |
| | | */ |
| | | function push() { |
| | | var name, |
| | | value, |
| | | browserCookies, |
| | | updated; |
| | | |
| | | //delete any cookies deleted in $cookies |
| | | for (name in lastCookies) { |
| | | if (isUndefined(cookies[name])) { |
| | | $browser.cookies(name, undefined); |
| | | } |
| | | } |
| | | |
| | | //update all cookies updated in $cookies |
| | | for(name in cookies) { |
| | | value = cookies[name]; |
| | | if (!angular.isString(value)) { |
| | | value = '' + value; |
| | | cookies[name] = value; |
| | | } |
| | | if (value !== lastCookies[name]) { |
| | | $browser.cookies(name, value); |
| | | updated = true; |
| | | } |
| | | } |
| | | |
| | | //verify what was actually stored |
| | | if (updated){ |
| | | updated = false; |
| | | browserCookies = $browser.cookies(); |
| | | |
| | | for (name in cookies) { |
| | | if (cookies[name] !== browserCookies[name]) { |
| | | //delete or reset all cookies that the browser dropped from $cookies |
| | | if (isUndefined(browserCookies[name])) { |
| | | delete cookies[name]; |
| | | } else { |
| | | cookies[name] = browserCookies[name]; |
| | | } |
| | | updated = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }]). |
| | | |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $cookieStore |
| | | * @requires $cookies |
| | | * |
| | | * @description |
| | | * Provides a key-value (string-object) storage, that is backed by session cookies. |
| | | * Objects put or retrieved from this storage are automatically serialized or |
| | | * deserialized by angular's toJson/fromJson. |
| | | * |
| | | * Requires the {@link ngCookies `ngCookies`} module to be installed. |
| | | * |
| | | * @example |
| | | * |
| | | * ```js |
| | | * function ExampleController($cookies) { |
| | | * // Put cookie |
| | | * $cookieStore.put('myFavorite','oatmeal'); |
| | | * // Get cookie |
| | | * var favoriteCookie = $cookieStore.get('myFavorite'); |
| | | * // Removing a cookie |
| | | * $cookieStore.remove('myFavorite'); |
| | | * } |
| | | * ``` |
| | | */ |
| | | factory('$cookieStore', ['$cookies', function($cookies) { |
| | | |
| | | return { |
| | | /** |
| | | * @ngdoc method |
| | | * @name $cookieStore#get |
| | | * |
| | | * @description |
| | | * Returns the value of given cookie key |
| | | * |
| | | * @param {string} key Id to use for lookup. |
| | | * @returns {Object} Deserialized cookie value. |
| | | */ |
| | | get: function(key) { |
| | | var value = $cookies[key]; |
| | | return value ? angular.fromJson(value) : value; |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $cookieStore#put |
| | | * |
| | | * @description |
| | | * Sets a value for given cookie key |
| | | * |
| | | * @param {string} key Id for the `value`. |
| | | * @param {Object} value Value to be stored. |
| | | */ |
| | | put: function(key, value) { |
| | | $cookies[key] = angular.toJson(value); |
| | | }, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $cookieStore#remove |
| | | * |
| | | * @description |
| | | * Remove given cookie |
| | | * |
| | | * @param {string} key Id of the key-value pair to delete. |
| | | */ |
| | | remove: function(key) { |
| | | delete $cookies[key]; |
| | | } |
| | | }; |
| | | |
| | | }]); |
| | | |
| | | |
| | | })(window, window.angular); |
New file |
| | |
| | | /* |
| | | AngularJS v1.2.18 |
| | | (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | License: MIT |
| | | */ |
| | | (function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore", |
| | | ["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular); |
| | | //# sourceMappingURL=angular-cookies.min.js.map |
New file |
| | |
| | | { |
| | | "version":3, |
| | | "file":"angular-cookies.min.js", |
| | | "lineCount":7, |
| | | "mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CAyBW,UAzBX,CAyBuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BqE,CAA3D,CAzBvB,CAAAH,QAAA,CAkIW,cAlIX;AAkI2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,KAWAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,KA0BAQ,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,QAuCGU,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CAlI3B,CAnBsC,CAArC,CAAA,CAsMEzB,MAtMF,CAsMUA,MAAAC,QAtMV;", |
| | | "sources":["angular-cookies.js"], |
| | | "names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] |
| | | } |
New file |
| | |
| | | /* Include this file in your html if you are using the CSP mode. */ |
| | | |
| | | @charset "UTF-8"; |
| | | |
| | | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], |
| | | .ng-cloak, .x-ng-cloak, |
| | | .ng-hide { |
| | | display: none !important; |
| | | } |
| | | |
| | | ng\:form { |
| | | display: block; |
| | | } |
| | | |
| | | .ng-animate-block-transitions { |
| | | transition:0s all!important; |
| | | -webkit-transition:0s all!important; |
| | | } |
| | | |
| | | /* show the element during a show/hide animation when the |
| | | * animation is ongoing, but the .ng-hide class is active */ |
| | | .ng-hide-add-active, .ng-hide-remove { |
| | | display: block!important; |
| | | } |
New file |
| | |
| | | /** |
| | | * @license AngularJS v1.2.18 |
| | | * (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | * License: MIT |
| | | */ |
| | | |
| | | (function() {'use strict'; |
| | | |
| | | /** |
| | | * @description |
| | | * |
| | | * This object provides a utility for producing rich Error messages within |
| | | * Angular. It can be called as follows: |
| | | * |
| | | * var exampleMinErr = minErr('example'); |
| | | * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); |
| | | * |
| | | * The above creates an instance of minErr in the example namespace. The |
| | | * resulting error will have a namespaced error code of example.one. The |
| | | * resulting error will replace {0} with the value of foo, and {1} with the |
| | | * value of bar. The object is not restricted in the number of arguments it can |
| | | * take. |
| | | * |
| | | * If fewer arguments are specified than necessary for interpolation, the extra |
| | | * interpolation markers will be preserved in the final string. |
| | | * |
| | | * Since data will be parsed statically during a build step, some restrictions |
| | | * are applied with respect to how minErr instances are created and called. |
| | | * Instances should have names of the form namespaceMinErr for a minErr created |
| | | * using minErr('namespace') . Error codes, namespaces and template strings |
| | | * should all be static strings, not variables or general expressions. |
| | | * |
| | | * @param {string} module The namespace to use for the new minErr instance. |
| | | * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance |
| | | */ |
| | | |
| | | function minErr(module) { |
| | | return function () { |
| | | var code = arguments[0], |
| | | prefix = '[' + (module ? module + ':' : '') + code + '] ', |
| | | template = arguments[1], |
| | | templateArgs = arguments, |
| | | stringify = function (obj) { |
| | | if (typeof obj === 'function') { |
| | | return obj.toString().replace(/ \{[\s\S]*$/, ''); |
| | | } else if (typeof obj === 'undefined') { |
| | | return 'undefined'; |
| | | } else if (typeof obj !== 'string') { |
| | | return JSON.stringify(obj); |
| | | } |
| | | return obj; |
| | | }, |
| | | message, i; |
| | | |
| | | message = prefix + template.replace(/\{\d+\}/g, function (match) { |
| | | var index = +match.slice(1, -1), arg; |
| | | |
| | | if (index + 2 < templateArgs.length) { |
| | | arg = templateArgs[index + 2]; |
| | | if (typeof arg === 'function') { |
| | | return arg.toString().replace(/ ?\{[\s\S]*$/, ''); |
| | | } else if (typeof arg === 'undefined') { |
| | | return 'undefined'; |
| | | } else if (typeof arg !== 'string') { |
| | | return toJson(arg); |
| | | } |
| | | return arg; |
| | | } |
| | | return match; |
| | | }); |
| | | |
| | | message = message + '\nhttp://errors.angularjs.org/1.2.18/' + |
| | | (module ? module + '/' : '') + code; |
| | | for (i = 2; i < arguments.length; i++) { |
| | | message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + |
| | | encodeURIComponent(stringify(arguments[i])); |
| | | } |
| | | |
| | | return new Error(message); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc type |
| | | * @name angular.Module |
| | | * @module ng |
| | | * @description |
| | | * |
| | | * Interface for configuring angular {@link angular.module modules}. |
| | | */ |
| | | |
| | | function setupModuleLoader(window) { |
| | | |
| | | var $injectorMinErr = minErr('$injector'); |
| | | var ngMinErr = minErr('ng'); |
| | | |
| | | function ensure(obj, name, factory) { |
| | | return obj[name] || (obj[name] = factory()); |
| | | } |
| | | |
| | | var angular = ensure(window, 'angular', Object); |
| | | |
| | | // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap |
| | | angular.$$minErr = angular.$$minErr || minErr; |
| | | |
| | | return ensure(angular, 'module', function() { |
| | | /** @type {Object.<string, angular.Module>} */ |
| | | var modules = {}; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name angular.module |
| | | * @module ng |
| | | * @description |
| | | * |
| | | * The `angular.module` is a global place for creating, registering and retrieving Angular |
| | | * modules. |
| | | * All modules (angular core or 3rd party) that should be available to an application must be |
| | | * registered using this mechanism. |
| | | * |
| | | * When passed two or more arguments, a new module is created. If passed only one argument, an |
| | | * existing module (the name passed as the first argument to `module`) is retrieved. |
| | | * |
| | | * |
| | | * # Module |
| | | * |
| | | * A module is a collection of services, directives, controllers, filters, and configuration information. |
| | | * `angular.module` is used to configure the {@link auto.$injector $injector}. |
| | | * |
| | | * ```js |
| | | * // Create a new module |
| | | * var myModule = angular.module('myModule', []); |
| | | * |
| | | * // register a new service |
| | | * myModule.value('appName', 'MyCoolApp'); |
| | | * |
| | | * // configure existing services inside initialization blocks. |
| | | * myModule.config(['$locationProvider', function($locationProvider) { |
| | | * // Configure existing providers |
| | | * $locationProvider.hashPrefix('!'); |
| | | * }]); |
| | | * ``` |
| | | * |
| | | * Then you can create an injector and load your modules like this: |
| | | * |
| | | * ```js |
| | | * var injector = angular.injector(['ng', 'myModule']) |
| | | * ``` |
| | | * |
| | | * However it's more likely that you'll just use |
| | | * {@link ng.directive:ngApp ngApp} or |
| | | * {@link angular.bootstrap} to simplify this process for you. |
| | | * |
| | | * @param {!string} name The name of the module to create or retrieve. |
| | | * @param {!Array.<string>=} requires If specified then new module is being created. If |
| | | * unspecified then the module is being retrieved for further configuration. |
| | | * @param {Function=} configFn Optional configuration function for the module. Same as |
| | | * {@link angular.Module#config Module#config()}. |
| | | * @returns {module} new module with the {@link angular.Module} api. |
| | | */ |
| | | return function module(name, requires, configFn) { |
| | | var assertNotHasOwnProperty = function(name, context) { |
| | | if (name === 'hasOwnProperty') { |
| | | throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); |
| | | } |
| | | }; |
| | | |
| | | assertNotHasOwnProperty(name, 'module'); |
| | | if (requires && modules.hasOwnProperty(name)) { |
| | | modules[name] = null; |
| | | } |
| | | return ensure(modules, name, function() { |
| | | if (!requires) { |
| | | throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + |
| | | "the module name or forgot to load it. If registering a module ensure that you " + |
| | | "specify the dependencies as the second argument.", name); |
| | | } |
| | | |
| | | /** @type {!Array.<Array.<*>>} */ |
| | | var invokeQueue = []; |
| | | |
| | | /** @type {!Array.<Function>} */ |
| | | var runBlocks = []; |
| | | |
| | | var config = invokeLater('$injector', 'invoke'); |
| | | |
| | | /** @type {angular.Module} */ |
| | | var moduleInstance = { |
| | | // Private state |
| | | _invokeQueue: invokeQueue, |
| | | _runBlocks: runBlocks, |
| | | |
| | | /** |
| | | * @ngdoc property |
| | | * @name angular.Module#requires |
| | | * @module ng |
| | | * @returns {Array.<string>} List of module names which must be loaded before this module. |
| | | * @description |
| | | * Holds the list of modules which the injector will load before the current module is |
| | | * loaded. |
| | | */ |
| | | requires: requires, |
| | | |
| | | /** |
| | | * @ngdoc property |
| | | * @name angular.Module#name |
| | | * @module ng |
| | | * @returns {string} Name of the module. |
| | | * @description |
| | | */ |
| | | name: name, |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#provider |
| | | * @module ng |
| | | * @param {string} name service name |
| | | * @param {Function} providerType Construction function for creating new instance of the |
| | | * service. |
| | | * @description |
| | | * See {@link auto.$provide#provider $provide.provider()}. |
| | | */ |
| | | provider: invokeLater('$provide', 'provider'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#factory |
| | | * @module ng |
| | | * @param {string} name service name |
| | | * @param {Function} providerFunction Function for creating new instance of the service. |
| | | * @description |
| | | * See {@link auto.$provide#factory $provide.factory()}. |
| | | */ |
| | | factory: invokeLater('$provide', 'factory'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#service |
| | | * @module ng |
| | | * @param {string} name service name |
| | | * @param {Function} constructor A constructor function that will be instantiated. |
| | | * @description |
| | | * See {@link auto.$provide#service $provide.service()}. |
| | | */ |
| | | service: invokeLater('$provide', 'service'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#value |
| | | * @module ng |
| | | * @param {string} name service name |
| | | * @param {*} object Service instance object. |
| | | * @description |
| | | * See {@link auto.$provide#value $provide.value()}. |
| | | */ |
| | | value: invokeLater('$provide', 'value'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#constant |
| | | * @module ng |
| | | * @param {string} name constant name |
| | | * @param {*} object Constant value. |
| | | * @description |
| | | * Because the constant are fixed, they get applied before other provide methods. |
| | | * See {@link auto.$provide#constant $provide.constant()}. |
| | | */ |
| | | constant: invokeLater('$provide', 'constant', 'unshift'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#animation |
| | | * @module ng |
| | | * @param {string} name animation name |
| | | * @param {Function} animationFactory Factory function for creating new instance of an |
| | | * animation. |
| | | * @description |
| | | * |
| | | * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. |
| | | * |
| | | * |
| | | * Defines an animation hook that can be later used with |
| | | * {@link ngAnimate.$animate $animate} service and directives that use this service. |
| | | * |
| | | * ```js |
| | | * module.animation('.animation-name', function($inject1, $inject2) { |
| | | * return { |
| | | * eventName : function(element, done) { |
| | | * //code to run the animation |
| | | * //once complete, then run done() |
| | | * return function cancellationFunction(element) { |
| | | * //code to cancel the animation |
| | | * } |
| | | * } |
| | | * } |
| | | * }) |
| | | * ``` |
| | | * |
| | | * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and |
| | | * {@link ngAnimate ngAnimate module} for more information. |
| | | */ |
| | | animation: invokeLater('$animateProvider', 'register'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#filter |
| | | * @module ng |
| | | * @param {string} name Filter name. |
| | | * @param {Function} filterFactory Factory function for creating new instance of filter. |
| | | * @description |
| | | * See {@link ng.$filterProvider#register $filterProvider.register()}. |
| | | */ |
| | | filter: invokeLater('$filterProvider', 'register'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#controller |
| | | * @module ng |
| | | * @param {string|Object} name Controller name, or an object map of controllers where the |
| | | * keys are the names and the values are the constructors. |
| | | * @param {Function} constructor Controller constructor function. |
| | | * @description |
| | | * See {@link ng.$controllerProvider#register $controllerProvider.register()}. |
| | | */ |
| | | controller: invokeLater('$controllerProvider', 'register'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#directive |
| | | * @module ng |
| | | * @param {string|Object} name Directive name, or an object map of directives where the |
| | | * keys are the names and the values are the factories. |
| | | * @param {Function} directiveFactory Factory function for creating new instance of |
| | | * directives. |
| | | * @description |
| | | * See {@link ng.$compileProvider#directive $compileProvider.directive()}. |
| | | */ |
| | | directive: invokeLater('$compileProvider', 'directive'), |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#config |
| | | * @module ng |
| | | * @param {Function} configFn Execute this function on module load. Useful for service |
| | | * configuration. |
| | | * @description |
| | | * Use this method to register work which needs to be performed on module loading. |
| | | * For more about how to configure services, see |
| | | * {@link providers#providers_provider-recipe Provider Recipe}. |
| | | */ |
| | | config: config, |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name angular.Module#run |
| | | * @module ng |
| | | * @param {Function} initializationFn Execute this function after injector creation. |
| | | * Useful for application initialization. |
| | | * @description |
| | | * Use this method to register work which should be performed when the injector is done |
| | | * loading all modules. |
| | | */ |
| | | run: function(block) { |
| | | runBlocks.push(block); |
| | | return this; |
| | | } |
| | | }; |
| | | |
| | | if (configFn) { |
| | | config(configFn); |
| | | } |
| | | |
| | | return moduleInstance; |
| | | |
| | | /** |
| | | * @param {string} provider |
| | | * @param {string} method |
| | | * @param {String=} insertMethod |
| | | * @returns {angular.Module} |
| | | */ |
| | | function invokeLater(provider, method, insertMethod) { |
| | | return function() { |
| | | invokeQueue[insertMethod || 'push']([provider, method, arguments]); |
| | | return moduleInstance; |
| | | }; |
| | | } |
| | | }); |
| | | }; |
| | | }); |
| | | |
| | | } |
| | | |
| | | setupModuleLoader(window); |
| | | })(window); |
| | | |
| | | /** |
| | | * Closure compiler type information |
| | | * |
| | | * @typedef { { |
| | | * requires: !Array.<string>, |
| | | * invokeQueue: !Array.<Array.<*>>, |
| | | * |
| | | * service: function(string, Function):angular.Module, |
| | | * factory: function(string, Function):angular.Module, |
| | | * value: function(string, *):angular.Module, |
| | | * |
| | | * filter: function(string, Function):angular.Module, |
| | | * |
| | | * init: function(Function):angular.Module |
| | | * } } |
| | | */ |
| | | angular.Module; |
| | | |
New file |
| | |
| | | /* |
| | | AngularJS v1.2.18 |
| | | (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | License: MIT |
| | | */ |
| | | (function(){'use strict';function d(a){return function(){var c=arguments[0],b,c="["+(a?a+":":"")+c+"] http://errors.angularjs.org/1.2.18/"+(a?a+"/":"")+c;for(b=1;b<arguments.length;b++)c=c+(1==b?"?":"&")+"p"+(b-1)+"="+encodeURIComponent("function"==typeof arguments[b]?arguments[b].toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof arguments[b]?"undefined":"string"!=typeof arguments[b]?JSON.stringify(arguments[b]):arguments[b]);return Error(c)}}(function(a){var c=d("$injector"),b=d("ng");a=a.angular|| |
| | | (a.angular={});a.$$minErr=a.$$minErr||d;return a.module||(a.module=function(){var a={};return function(e,d,f){if("hasOwnProperty"===e)throw b("badname","module");d&&a.hasOwnProperty(e)&&(a[e]=null);return a[e]||(a[e]=function(){function a(c,d,e){return function(){b[e||"push"]([c,d,arguments]);return g}}if(!d)throw c("nomod",e);var b=[],h=[],k=a("$injector","invoke"),g={_invokeQueue:b,_runBlocks:h,requires:d,name:e,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide", |
| | | "service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:k,run:function(a){h.push(a);return this}};f&&k(f);return g}())}}())})(window)})(window); |
| | | //# sourceMappingURL=angular-loader.min.js.map |
New file |
| | |
| | | { |
| | | "version":3, |
| | | "file":"angular-loader.min.js", |
| | | "lineCount":8, |
| | | "mappings":"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", |
| | | "sources":["angular-loader.js"], |
| | | "names":["minErr","setupModuleLoader","window","$injectorMinErr","ngMinErr","angular","$$minErr","factory","modules","module","name","requires","configFn","context","hasOwnProperty","invokeLater","provider","method","insertMethod","invokeQueue","arguments","moduleInstance","runBlocks","config","run","block","push"] |
| | | } |
New file |
| | |
| | | /** |
| | | * @license AngularJS v1.2.18 |
| | | * (c) 2010-2014 Google, Inc. http://angularjs.org |
| | | * License: MIT |
| | | */ |
| | | (function(window, angular, undefined) { |
| | | |
| | | 'use strict'; |
| | | |
| | | /** |
| | | * @ngdoc object |
| | | * @name angular.mock |
| | | * @description |
| | | * |
| | | * Namespace from 'angular-mocks.js' which contains testing related code. |
| | | */ |
| | | angular.mock = {}; |
| | | |
| | | /** |
| | | * ! This is a private undocumented service ! |
| | | * |
| | | * @name $browser |
| | | * |
| | | * @description |
| | | * This service is a mock implementation of {@link ng.$browser}. It provides fake |
| | | * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr, |
| | | * cookies, etc... |
| | | * |
| | | * The api of this service is the same as that of the real {@link ng.$browser $browser}, except |
| | | * that there are several helper methods available which can be used in tests. |
| | | */ |
| | | angular.mock.$BrowserProvider = function() { |
| | | this.$get = function() { |
| | | return new angular.mock.$Browser(); |
| | | }; |
| | | }; |
| | | |
| | | angular.mock.$Browser = function() { |
| | | var self = this; |
| | | |
| | | this.isMock = true; |
| | | self.$$url = "http://server/"; |
| | | self.$$lastUrl = self.$$url; // used by url polling fn |
| | | self.pollFns = []; |
| | | |
| | | // TODO(vojta): remove this temporary api |
| | | self.$$completeOutstandingRequest = angular.noop; |
| | | self.$$incOutstandingRequestCount = angular.noop; |
| | | |
| | | |
| | | // register url polling fn |
| | | |
| | | self.onUrlChange = function(listener) { |
| | | self.pollFns.push( |
| | | function() { |
| | | if (self.$$lastUrl != self.$$url) { |
| | | self.$$lastUrl = self.$$url; |
| | | listener(self.$$url); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | return listener; |
| | | }; |
| | | |
| | | self.cookieHash = {}; |
| | | self.lastCookieHash = {}; |
| | | self.deferredFns = []; |
| | | self.deferredNextId = 0; |
| | | |
| | | self.defer = function(fn, delay) { |
| | | delay = delay || 0; |
| | | self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId}); |
| | | self.deferredFns.sort(function(a,b){ return a.time - b.time;}); |
| | | return self.deferredNextId++; |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @name $browser#defer.now |
| | | * |
| | | * @description |
| | | * Current milliseconds mock time. |
| | | */ |
| | | self.defer.now = 0; |
| | | |
| | | |
| | | self.defer.cancel = function(deferId) { |
| | | var fnIndex; |
| | | |
| | | angular.forEach(self.deferredFns, function(fn, index) { |
| | | if (fn.id === deferId) fnIndex = index; |
| | | }); |
| | | |
| | | if (fnIndex !== undefined) { |
| | | self.deferredFns.splice(fnIndex, 1); |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @name $browser#defer.flush |
| | | * |
| | | * @description |
| | | * Flushes all pending requests and executes the defer callbacks. |
| | | * |
| | | * @param {number=} number of milliseconds to flush. See {@link #defer.now} |
| | | */ |
| | | self.defer.flush = function(delay) { |
| | | if (angular.isDefined(delay)) { |
| | | self.defer.now += delay; |
| | | } else { |
| | | if (self.deferredFns.length) { |
| | | self.defer.now = self.deferredFns[self.deferredFns.length-1].time; |
| | | } else { |
| | | throw new Error('No deferred tasks to be flushed'); |
| | | } |
| | | } |
| | | |
| | | while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { |
| | | self.deferredFns.shift().fn(); |
| | | } |
| | | }; |
| | | |
| | | self.$$baseHref = ''; |
| | | self.baseHref = function() { |
| | | return this.$$baseHref; |
| | | }; |
| | | }; |
| | | angular.mock.$Browser.prototype = { |
| | | |
| | | /** |
| | | * @name $browser#poll |
| | | * |
| | | * @description |
| | | * run all fns in pollFns |
| | | */ |
| | | poll: function poll() { |
| | | angular.forEach(this.pollFns, function(pollFn){ |
| | | pollFn(); |
| | | }); |
| | | }, |
| | | |
| | | addPollFn: function(pollFn) { |
| | | this.pollFns.push(pollFn); |
| | | return pollFn; |
| | | }, |
| | | |
| | | url: function(url, replace) { |
| | | if (url) { |
| | | this.$$url = url; |
| | | return this; |
| | | } |
| | | |
| | | return this.$$url; |
| | | }, |
| | | |
| | | cookies: function(name, value) { |
| | | if (name) { |
| | | if (angular.isUndefined(value)) { |
| | | delete this.cookieHash[name]; |
| | | } else { |
| | | if (angular.isString(value) && //strings only |
| | | value.length <= 4096) { //strict cookie storage limits |
| | | this.cookieHash[name] = value; |
| | | } |
| | | } |
| | | } else { |
| | | if (!angular.equals(this.cookieHash, this.lastCookieHash)) { |
| | | this.lastCookieHash = angular.copy(this.cookieHash); |
| | | this.cookieHash = angular.copy(this.cookieHash); |
| | | } |
| | | return this.cookieHash; |
| | | } |
| | | }, |
| | | |
| | | notifyWhenNoOutstandingRequests: function(fn) { |
| | | fn(); |
| | | } |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc provider |
| | | * @name $exceptionHandlerProvider |
| | | * |
| | | * @description |
| | | * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors |
| | | * passed into the `$exceptionHandler`. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $exceptionHandler |
| | | * |
| | | * @description |
| | | * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed |
| | | * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration |
| | | * information. |
| | | * |
| | | * |
| | | * ```js |
| | | * describe('$exceptionHandlerProvider', function() { |
| | | * |
| | | * it('should capture log messages and exceptions', function() { |
| | | * |
| | | * module(function($exceptionHandlerProvider) { |
| | | * $exceptionHandlerProvider.mode('log'); |
| | | * }); |
| | | * |
| | | * inject(function($log, $exceptionHandler, $timeout) { |
| | | * $timeout(function() { $log.log(1); }); |
| | | * $timeout(function() { $log.log(2); throw 'banana peel'; }); |
| | | * $timeout(function() { $log.log(3); }); |
| | | * expect($exceptionHandler.errors).toEqual([]); |
| | | * expect($log.assertEmpty()); |
| | | * $timeout.flush(); |
| | | * expect($exceptionHandler.errors).toEqual(['banana peel']); |
| | | * expect($log.log.logs).toEqual([[1], [2], [3]]); |
| | | * }); |
| | | * }); |
| | | * }); |
| | | * ``` |
| | | */ |
| | | |
| | | angular.mock.$ExceptionHandlerProvider = function() { |
| | | var handler; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $exceptionHandlerProvider#mode |
| | | * |
| | | * @description |
| | | * Sets the logging mode. |
| | | * |
| | | * @param {string} mode Mode of operation, defaults to `rethrow`. |
| | | * |
| | | * - `rethrow`: If any errors are passed into the handler in tests, it typically |
| | | * means that there is a bug in the application or test, so this mock will |
| | | * make these tests fail. |
| | | * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` |
| | | * mode stores an array of errors in `$exceptionHandler.errors`, to allow later |
| | | * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and |
| | | * {@link ngMock.$log#reset reset()} |
| | | */ |
| | | this.mode = function(mode) { |
| | | switch(mode) { |
| | | case 'rethrow': |
| | | handler = function(e) { |
| | | throw e; |
| | | }; |
| | | break; |
| | | case 'log': |
| | | var errors = []; |
| | | |
| | | handler = function(e) { |
| | | if (arguments.length == 1) { |
| | | errors.push(e); |
| | | } else { |
| | | errors.push([].slice.call(arguments, 0)); |
| | | } |
| | | }; |
| | | |
| | | handler.errors = errors; |
| | | break; |
| | | default: |
| | | throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); |
| | | } |
| | | }; |
| | | |
| | | this.$get = function() { |
| | | return handler; |
| | | }; |
| | | |
| | | this.mode('rethrow'); |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $log |
| | | * |
| | | * @description |
| | | * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays |
| | | * (one array per logging level). These arrays are exposed as `logs` property of each of the |
| | | * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. |
| | | * |
| | | */ |
| | | angular.mock.$LogProvider = function() { |
| | | var debug = true; |
| | | |
| | | function concat(array1, array2, index) { |
| | | return array1.concat(Array.prototype.slice.call(array2, index)); |
| | | } |
| | | |
| | | this.debugEnabled = function(flag) { |
| | | if (angular.isDefined(flag)) { |
| | | debug = flag; |
| | | return this; |
| | | } else { |
| | | return debug; |
| | | } |
| | | }; |
| | | |
| | | this.$get = function () { |
| | | var $log = { |
| | | log: function() { $log.log.logs.push(concat([], arguments, 0)); }, |
| | | warn: function() { $log.warn.logs.push(concat([], arguments, 0)); }, |
| | | info: function() { $log.info.logs.push(concat([], arguments, 0)); }, |
| | | error: function() { $log.error.logs.push(concat([], arguments, 0)); }, |
| | | debug: function() { |
| | | if (debug) { |
| | | $log.debug.logs.push(concat([], arguments, 0)); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $log#reset |
| | | * |
| | | * @description |
| | | * Reset all of the logging arrays to empty. |
| | | */ |
| | | $log.reset = function () { |
| | | /** |
| | | * @ngdoc property |
| | | * @name $log#log.logs |
| | | * |
| | | * @description |
| | | * Array of messages logged using {@link ngMock.$log#log}. |
| | | * |
| | | * @example |
| | | * ```js |
| | | * $log.log('Some Log'); |
| | | * var first = $log.log.logs.unshift(); |
| | | * ``` |
| | | */ |
| | | $log.log.logs = []; |
| | | /** |
| | | * @ngdoc property |
| | | * @name $log#info.logs |
| | | * |
| | | * @description |
| | | * Array of messages logged using {@link ngMock.$log#info}. |
| | | * |
| | | * @example |
| | | * ```js |
| | | * $log.info('Some Info'); |
| | | * var first = $log.info.logs.unshift(); |
| | | * ``` |
| | | */ |
| | | $log.info.logs = []; |
| | | /** |
| | | * @ngdoc property |
| | | * @name $log#warn.logs |
| | | * |
| | | * @description |
| | | * Array of messages logged using {@link ngMock.$log#warn}. |
| | | * |
| | | * @example |
| | | * ```js |
| | | * $log.warn('Some Warning'); |
| | | * var first = $log.warn.logs.unshift(); |
| | | * ``` |
| | | */ |
| | | $log.warn.logs = []; |
| | | /** |
| | | * @ngdoc property |
| | | * @name $log#error.logs |
| | | * |
| | | * @description |
| | | * Array of messages logged using {@link ngMock.$log#error}. |
| | | * |
| | | * @example |
| | | * ```js |
| | | * $log.error('Some Error'); |
| | | * var first = $log.error.logs.unshift(); |
| | | * ``` |
| | | */ |
| | | $log.error.logs = []; |
| | | /** |
| | | * @ngdoc property |
| | | * @name $log#debug.logs |
| | | * |
| | | * @description |
| | | * Array of messages logged using {@link ngMock.$log#debug}. |
| | | * |
| | | * @example |
| | | * ```js |
| | | * $log.debug('Some Error'); |
| | | * var first = $log.debug.logs.unshift(); |
| | | * ``` |
| | | */ |
| | | $log.debug.logs = []; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $log#assertEmpty |
| | | * |
| | | * @description |
| | | * Assert that the all of the logging methods have no logged messages. If messages present, an |
| | | * exception is thrown. |
| | | */ |
| | | $log.assertEmpty = function() { |
| | | var errors = []; |
| | | angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) { |
| | | angular.forEach($log[logLevel].logs, function(log) { |
| | | angular.forEach(log, function (logItem) { |
| | | errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + |
| | | (logItem.stack || '')); |
| | | }); |
| | | }); |
| | | }); |
| | | if (errors.length) { |
| | | errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+ |
| | | "an expected log message was not checked and removed:"); |
| | | errors.push(''); |
| | | throw new Error(errors.join('\n---------\n')); |
| | | } |
| | | }; |
| | | |
| | | $log.reset(); |
| | | return $log; |
| | | }; |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $interval |
| | | * |
| | | * @description |
| | | * Mock implementation of the $interval service. |
| | | * |
| | | * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to |
| | | * move forward by `millis` milliseconds and trigger any functions scheduled to run in that |
| | | * time. |
| | | * |
| | | * @param {function()} fn A function that should be called repeatedly. |
| | | * @param {number} delay Number of milliseconds between each function call. |
| | | * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat |
| | | * indefinitely. |
| | | * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise |
| | | * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. |
| | | * @returns {promise} A promise which will be notified on each iteration. |
| | | */ |
| | | angular.mock.$IntervalProvider = function() { |
| | | this.$get = ['$rootScope', '$q', |
| | | function($rootScope, $q) { |
| | | var repeatFns = [], |
| | | nextRepeatId = 0, |
| | | now = 0; |
| | | |
| | | var $interval = function(fn, delay, count, invokeApply) { |
| | | var deferred = $q.defer(), |
| | | promise = deferred.promise, |
| | | iteration = 0, |
| | | skipApply = (angular.isDefined(invokeApply) && !invokeApply); |
| | | |
| | | count = (angular.isDefined(count)) ? count : 0, |
| | | promise.then(null, null, fn); |
| | | |
| | | promise.$$intervalId = nextRepeatId; |
| | | |
| | | function tick() { |
| | | deferred.notify(iteration++); |
| | | |
| | | if (count > 0 && iteration >= count) { |
| | | var fnIndex; |
| | | deferred.resolve(iteration); |
| | | |
| | | angular.forEach(repeatFns, function(fn, index) { |
| | | if (fn.id === promise.$$intervalId) fnIndex = index; |
| | | }); |
| | | |
| | | if (fnIndex !== undefined) { |
| | | repeatFns.splice(fnIndex, 1); |
| | | } |
| | | } |
| | | |
| | | if (!skipApply) $rootScope.$apply(); |
| | | } |
| | | |
| | | repeatFns.push({ |
| | | nextTime:(now + delay), |
| | | delay: delay, |
| | | fn: tick, |
| | | id: nextRepeatId, |
| | | deferred: deferred |
| | | }); |
| | | repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); |
| | | |
| | | nextRepeatId++; |
| | | return promise; |
| | | }; |
| | | /** |
| | | * @ngdoc method |
| | | * @name $interval#cancel |
| | | * |
| | | * @description |
| | | * Cancels a task associated with the `promise`. |
| | | * |
| | | * @param {promise} promise A promise from calling the `$interval` function. |
| | | * @returns {boolean} Returns `true` if the task was successfully cancelled. |
| | | */ |
| | | $interval.cancel = function(promise) { |
| | | if(!promise) return false; |
| | | var fnIndex; |
| | | |
| | | angular.forEach(repeatFns, function(fn, index) { |
| | | if (fn.id === promise.$$intervalId) fnIndex = index; |
| | | }); |
| | | |
| | | if (fnIndex !== undefined) { |
| | | repeatFns[fnIndex].deferred.reject('canceled'); |
| | | repeatFns.splice(fnIndex, 1); |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $interval#flush |
| | | * @description |
| | | * |
| | | * Runs interval tasks scheduled to be run in the next `millis` milliseconds. |
| | | * |
| | | * @param {number=} millis maximum timeout amount to flush up until. |
| | | * |
| | | * @return {number} The amount of time moved forward. |
| | | */ |
| | | $interval.flush = function(millis) { |
| | | now += millis; |
| | | while (repeatFns.length && repeatFns[0].nextTime <= now) { |
| | | var task = repeatFns[0]; |
| | | task.fn(); |
| | | task.nextTime += task.delay; |
| | | repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); |
| | | } |
| | | return millis; |
| | | }; |
| | | |
| | | return $interval; |
| | | }]; |
| | | }; |
| | | |
| | | |
| | | /* jshint -W101 */ |
| | | /* The R_ISO8061_STR regex is never going to fit into the 100 char limit! |
| | | * This directive should go inside the anonymous function but a bug in JSHint means that it would |
| | | * not be enacted early enough to prevent the warning. |
| | | */ |
| | | var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; |
| | | |
| | | function jsonStringToDate(string) { |
| | | var match; |
| | | if (match = string.match(R_ISO8061_STR)) { |
| | | var date = new Date(0), |
| | | tzHour = 0, |
| | | tzMin = 0; |
| | | if (match[9]) { |
| | | tzHour = int(match[9] + match[10]); |
| | | tzMin = int(match[9] + match[11]); |
| | | } |
| | | date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); |
| | | date.setUTCHours(int(match[4]||0) - tzHour, |
| | | int(match[5]||0) - tzMin, |
| | | int(match[6]||0), |
| | | int(match[7]||0)); |
| | | return date; |
| | | } |
| | | return string; |
| | | } |
| | | |
| | | function int(str) { |
| | | return parseInt(str, 10); |
| | | } |
| | | |
| | | function padNumber(num, digits, trim) { |
| | | var neg = ''; |
| | | if (num < 0) { |
| | | neg = '-'; |
| | | num = -num; |
| | | } |
| | | num = '' + num; |
| | | while(num.length < digits) num = '0' + num; |
| | | if (trim) |
| | | num = num.substr(num.length - digits); |
| | | return neg + num; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @ngdoc type |
| | | * @name angular.mock.TzDate |
| | | * @description |
| | | * |
| | | * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. |
| | | * |
| | | * Mock of the Date type which has its timezone specified via constructor arg. |
| | | * |
| | | * The main purpose is to create Date-like instances with timezone fixed to the specified timezone |
| | | * offset, so that we can test code that depends on local timezone settings without dependency on |
| | | * the time zone settings of the machine where the code is running. |
| | | * |
| | | * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) |
| | | * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* |
| | | * |
| | | * @example |
| | | * !!!! WARNING !!!!! |
| | | * This is not a complete Date object so only methods that were implemented can be called safely. |
| | | * To make matters worse, TzDate instances inherit stuff from Date via a prototype. |
| | | * |
| | | * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is |
| | | * incomplete we might be missing some non-standard methods. This can result in errors like: |
| | | * "Date.prototype.foo called on incompatible Object". |
| | | * |
| | | * ```js |
| | | * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z'); |
| | | * newYearInBratislava.getTimezoneOffset() => -60; |
| | | * newYearInBratislava.getFullYear() => 2010; |
| | | * newYearInBratislava.getMonth() => 0; |
| | | * newYearInBratislava.getDate() => 1; |
| | | * newYearInBratislava.getHours() => 0; |
| | | * newYearInBratislava.getMinutes() => 0; |
| | | * newYearInBratislava.getSeconds() => 0; |
| | | * ``` |
| | | * |
| | | */ |
| | | angular.mock.TzDate = function (offset, timestamp) { |
| | | var self = new Date(0); |
| | | if (angular.isString(timestamp)) { |
| | | var tsStr = timestamp; |
| | | |
| | | self.origDate = jsonStringToDate(timestamp); |
| | | |
| | | timestamp = self.origDate.getTime(); |
| | | if (isNaN(timestamp)) |
| | | throw { |
| | | name: "Illegal Argument", |
| | | message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" |
| | | }; |
| | | } else { |
| | | self.origDate = new Date(timestamp); |
| | | } |
| | | |
| | | var localOffset = new Date(timestamp).getTimezoneOffset(); |
| | | self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; |
| | | self.date = new Date(timestamp + self.offsetDiff); |
| | | |
| | | self.getTime = function() { |
| | | return self.date.getTime() - self.offsetDiff; |
| | | }; |
| | | |
| | | self.toLocaleDateString = function() { |
| | | return self.date.toLocaleDateString(); |
| | | }; |
| | | |
| | | self.getFullYear = function() { |
| | | return self.date.getFullYear(); |
| | | }; |
| | | |
| | | self.getMonth = function() { |
| | | return self.date.getMonth(); |
| | | }; |
| | | |
| | | self.getDate = function() { |
| | | return self.date.getDate(); |
| | | }; |
| | | |
| | | self.getHours = function() { |
| | | return self.date.getHours(); |
| | | }; |
| | | |
| | | self.getMinutes = function() { |
| | | return self.date.getMinutes(); |
| | | }; |
| | | |
| | | self.getSeconds = function() { |
| | | return self.date.getSeconds(); |
| | | }; |
| | | |
| | | self.getMilliseconds = function() { |
| | | return self.date.getMilliseconds(); |
| | | }; |
| | | |
| | | self.getTimezoneOffset = function() { |
| | | return offset * 60; |
| | | }; |
| | | |
| | | self.getUTCFullYear = function() { |
| | | return self.origDate.getUTCFullYear(); |
| | | }; |
| | | |
| | | self.getUTCMonth = function() { |
| | | return self.origDate.getUTCMonth(); |
| | | }; |
| | | |
| | | self.getUTCDate = function() { |
| | | return self.origDate.getUTCDate(); |
| | | }; |
| | | |
| | | self.getUTCHours = function() { |
| | | return self.origDate.getUTCHours(); |
| | | }; |
| | | |
| | | self.getUTCMinutes = function() { |
| | | return self.origDate.getUTCMinutes(); |
| | | }; |
| | | |
| | | self.getUTCSeconds = function() { |
| | | return self.origDate.getUTCSeconds(); |
| | | }; |
| | | |
| | | self.getUTCMilliseconds = function() { |
| | | return self.origDate.getUTCMilliseconds(); |
| | | }; |
| | | |
| | | self.getDay = function() { |
| | | return self.date.getDay(); |
| | | }; |
| | | |
| | | // provide this method only on browsers that already have it |
| | | if (self.toISOString) { |
| | | self.toISOString = function() { |
| | | return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + |
| | | padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + |
| | | padNumber(self.origDate.getUTCDate(), 2) + 'T' + |
| | | padNumber(self.origDate.getUTCHours(), 2) + ':' + |
| | | padNumber(self.origDate.getUTCMinutes(), 2) + ':' + |
| | | padNumber(self.origDate.getUTCSeconds(), 2) + '.' + |
| | | padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; |
| | | }; |
| | | } |
| | | |
| | | //hide all methods not implemented in this mock that the Date prototype exposes |
| | | var unimplementedMethods = ['getUTCDay', |
| | | 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', |
| | | 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', |
| | | 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', |
| | | 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', |
| | | 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; |
| | | |
| | | angular.forEach(unimplementedMethods, function(methodName) { |
| | | self[methodName] = function() { |
| | | throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); |
| | | }; |
| | | }); |
| | | |
| | | return self; |
| | | }; |
| | | |
| | | //make "tzDateInstance instanceof Date" return true |
| | | angular.mock.TzDate.prototype = Date.prototype; |
| | | /* jshint +W101 */ |
| | | |
| | | angular.mock.animate = angular.module('ngAnimateMock', ['ng']) |
| | | |
| | | .config(['$provide', function($provide) { |
| | | |
| | | var reflowQueue = []; |
| | | $provide.value('$$animateReflow', function(fn) { |
| | | var index = reflowQueue.length; |
| | | reflowQueue.push(fn); |
| | | return function cancel() { |
| | | reflowQueue.splice(index, 1); |
| | | }; |
| | | }); |
| | | |
| | | $provide.decorator('$animate', function($delegate, $$asyncCallback) { |
| | | var animate = { |
| | | queue : [], |
| | | enabled : $delegate.enabled, |
| | | triggerCallbacks : function() { |
| | | $$asyncCallback.flush(); |
| | | }, |
| | | triggerReflow : function() { |
| | | angular.forEach(reflowQueue, function(fn) { |
| | | fn(); |
| | | }); |
| | | reflowQueue = []; |
| | | } |
| | | }; |
| | | |
| | | angular.forEach( |
| | | ['enter','leave','move','addClass','removeClass','setClass'], function(method) { |
| | | animate[method] = function() { |
| | | animate.queue.push({ |
| | | event : method, |
| | | element : arguments[0], |
| | | args : arguments |
| | | }); |
| | | $delegate[method].apply($delegate, arguments); |
| | | }; |
| | | }); |
| | | |
| | | return animate; |
| | | }); |
| | | |
| | | }]); |
| | | |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name angular.mock.dump |
| | | * @description |
| | | * |
| | | * *NOTE*: this is not an injectable instance, just a globally available function. |
| | | * |
| | | * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for |
| | | * debugging. |
| | | * |
| | | * This method is also available on window, where it can be used to display objects on debug |
| | | * console. |
| | | * |
| | | * @param {*} object - any object to turn into string. |
| | | * @return {string} a serialized string of the argument |
| | | */ |
| | | angular.mock.dump = function(object) { |
| | | return serialize(object); |
| | | |
| | | function serialize(object) { |
| | | var out; |
| | | |
| | | if (angular.isElement(object)) { |
| | | object = angular.element(object); |
| | | out = angular.element('<div></div>'); |
| | | angular.forEach(object, function(element) { |
| | | out.append(angular.element(element).clone()); |
| | | }); |
| | | out = out.html(); |
| | | } else if (angular.isArray(object)) { |
| | | out = []; |
| | | angular.forEach(object, function(o) { |
| | | out.push(serialize(o)); |
| | | }); |
| | | out = '[ ' + out.join(', ') + ' ]'; |
| | | } else if (angular.isObject(object)) { |
| | | if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { |
| | | out = serializeScope(object); |
| | | } else if (object instanceof Error) { |
| | | out = object.stack || ('' + object.name + ': ' + object.message); |
| | | } else { |
| | | // TODO(i): this prevents methods being logged, |
| | | // we should have a better way to serialize objects |
| | | out = angular.toJson(object, true); |
| | | } |
| | | } else { |
| | | out = String(object); |
| | | } |
| | | |
| | | return out; |
| | | } |
| | | |
| | | function serializeScope(scope, offset) { |
| | | offset = offset || ' '; |
| | | var log = [offset + 'Scope(' + scope.$id + '): {']; |
| | | for ( var key in scope ) { |
| | | if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { |
| | | log.push(' ' + key + ': ' + angular.toJson(scope[key])); |
| | | } |
| | | } |
| | | var child = scope.$$childHead; |
| | | while(child) { |
| | | log.push(serializeScope(child, offset + ' ')); |
| | | child = child.$$nextSibling; |
| | | } |
| | | log.push('}'); |
| | | return log.join('\n' + offset); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $httpBackend |
| | | * @description |
| | | * Fake HTTP backend implementation suitable for unit testing applications that use the |
| | | * {@link ng.$http $http service}. |
| | | * |
| | | * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less |
| | | * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. |
| | | * |
| | | * During unit testing, we want our unit tests to run quickly and have no external dependencies so |
| | | * we don’t want to send [XHR](https://developer.mozilla.org/en/xmlhttprequest) or |
| | | * [JSONP](http://en.wikipedia.org/wiki/JSONP) requests to a real server. All we really need is |
| | | * to verify whether a certain request has been sent or not, or alternatively just let the |
| | | * application make requests, respond with pre-trained responses and assert that the end result is |
| | | * what we expect it to be. |
| | | * |
| | | * This mock implementation can be used to respond with static or dynamic responses via the |
| | | * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). |
| | | * |
| | | * When an Angular application needs some data from a server, it calls the $http service, which |
| | | * sends the request to a real server using $httpBackend service. With dependency injection, it is |
| | | * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify |
| | | * the requests and respond with some testing data without sending a request to a real server. |
| | | * |
| | | * There are two ways to specify what test data should be returned as http responses by the mock |
| | | * backend when the code under test makes http requests: |
| | | * |
| | | * - `$httpBackend.expect` - specifies a request expectation |
| | | * - `$httpBackend.when` - specifies a backend definition |
| | | * |
| | | * |
| | | * # Request Expectations vs Backend Definitions |
| | | * |
| | | * Request expectations provide a way to make assertions about requests made by the application and |
| | | * to define responses for those requests. The test will fail if the expected requests are not made |
| | | * or they are made in the wrong order. |
| | | * |
| | | * Backend definitions allow you to define a fake backend for your application which doesn't assert |
| | | * if a particular request was made or not, it just returns a trained response if a request is made. |
| | | * The test will pass whether or not the request gets made during testing. |
| | | * |
| | | * |
| | | * <table class="table"> |
| | | * <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr> |
| | | * <tr> |
| | | * <th>Syntax</th> |
| | | * <td>.expect(...).respond(...)</td> |
| | | * <td>.when(...).respond(...)</td> |
| | | * </tr> |
| | | * <tr> |
| | | * <th>Typical usage</th> |
| | | * <td>strict unit tests</td> |
| | | * <td>loose (black-box) unit testing</td> |
| | | * </tr> |
| | | * <tr> |
| | | * <th>Fulfills multiple requests</th> |
| | | * <td>NO</td> |
| | | * <td>YES</td> |
| | | * </tr> |
| | | * <tr> |
| | | * <th>Order of requests matters</th> |
| | | * <td>YES</td> |
| | | * <td>NO</td> |
| | | * </tr> |
| | | * <tr> |
| | | * <th>Request required</th> |
| | | * <td>YES</td> |
| | | * <td>NO</td> |
| | | * </tr> |
| | | * <tr> |
| | | * <th>Response required</th> |
| | | * <td>optional (see below)</td> |
| | | * <td>YES</td> |
| | | * </tr> |
| | | * </table> |
| | | * |
| | | * In cases where both backend definitions and request expectations are specified during unit |
| | | * testing, the request expectations are evaluated first. |
| | | * |
| | | * If a request expectation has no response specified, the algorithm will search your backend |
| | | * definitions for an appropriate response. |
| | | * |
| | | * If a request didn't match any expectation or if the expectation doesn't have the response |
| | | * defined, the backend definitions are evaluated in sequential order to see if any of them match |
| | | * the request. The response from the first matched definition is returned. |
| | | * |
| | | * |
| | | * # Flushing HTTP requests |
| | | * |
| | | * The $httpBackend used in production always responds to requests asynchronously. If we preserved |
| | | * this behavior in unit testing, we'd have to create async unit tests, which are hard to write, |
| | | * to follow and to maintain. But neither can the testing mock respond synchronously; that would |
| | | * change the execution of the code under test. For this reason, the mock $httpBackend has a |
| | | * `flush()` method, which allows the test to explicitly flush pending requests. This preserves |
| | | * the async api of the backend, while allowing the test to execute synchronously. |
| | | * |
| | | * |
| | | * # Unit testing with mock $httpBackend |
| | | * The following code shows how to setup and use the mock backend when unit testing a controller. |
| | | * First we create the controller under test: |
| | | * |
| | | ```js |
| | | // The controller code |
| | | function MyController($scope, $http) { |
| | | var authToken; |
| | | |
| | | $http.get('/auth.py').success(function(data, status, headers) { |
| | | authToken = headers('A-Token'); |
| | | $scope.user = data; |
| | | }); |
| | | |
| | | $scope.saveMessage = function(message) { |
| | | var headers = { 'Authorization': authToken }; |
| | | $scope.status = 'Saving...'; |
| | | |
| | | $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) { |
| | | $scope.status = ''; |
| | | }).error(function() { |
| | | $scope.status = 'ERROR!'; |
| | | }); |
| | | }; |
| | | } |
| | | ``` |
| | | * |
| | | * Now we setup the mock backend and create the test specs: |
| | | * |
| | | ```js |
| | | // testing controller |
| | | describe('MyController', function() { |
| | | var $httpBackend, $rootScope, createController; |
| | | |
| | | beforeEach(inject(function($injector) { |
| | | // Set up the mock http service responses |
| | | $httpBackend = $injector.get('$httpBackend'); |
| | | // backend definition common for all tests |
| | | $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'}); |
| | | |
| | | // Get hold of a scope (i.e. the root scope) |
| | | $rootScope = $injector.get('$rootScope'); |
| | | // The $controller service is used to create instances of controllers |
| | | var $controller = $injector.get('$controller'); |
| | | |
| | | createController = function() { |
| | | return $controller('MyController', {'$scope' : $rootScope }); |
| | | }; |
| | | })); |
| | | |
| | | |
| | | afterEach(function() { |
| | | $httpBackend.verifyNoOutstandingExpectation(); |
| | | $httpBackend.verifyNoOutstandingRequest(); |
| | | }); |
| | | |
| | | |
| | | it('should fetch authentication token', function() { |
| | | $httpBackend.expectGET('/auth.py'); |
| | | var controller = createController(); |
| | | $httpBackend.flush(); |
| | | }); |
| | | |
| | | |
| | | it('should send msg to server', function() { |
| | | var controller = createController(); |
| | | $httpBackend.flush(); |
| | | |
| | | // now you don’t care about the authentication, but |
| | | // the controller will still send the request and |
| | | // $httpBackend will respond without you having to |
| | | // specify the expectation and response for this request |
| | | |
| | | $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, ''); |
| | | $rootScope.saveMessage('message content'); |
| | | expect($rootScope.status).toBe('Saving...'); |
| | | $httpBackend.flush(); |
| | | expect($rootScope.status).toBe(''); |
| | | }); |
| | | |
| | | |
| | | it('should send auth header', function() { |
| | | var controller = createController(); |
| | | $httpBackend.flush(); |
| | | |
| | | $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) { |
| | | // check if the header was send, if it wasn't the expectation won't |
| | | // match the request and the test will fail |
| | | return headers['Authorization'] == 'xxx'; |
| | | }).respond(201, ''); |
| | | |
| | | $rootScope.saveMessage('whatever'); |
| | | $httpBackend.flush(); |
| | | }); |
| | | }); |
| | | ``` |
| | | */ |
| | | angular.mock.$HttpBackendProvider = function() { |
| | | this.$get = ['$rootScope', createHttpBackendMock]; |
| | | }; |
| | | |
| | | /** |
| | | * General factory function for $httpBackend mock. |
| | | * Returns instance for unit testing (when no arguments specified): |
| | | * - passing through is disabled |
| | | * - auto flushing is disabled |
| | | * |
| | | * Returns instance for e2e testing (when `$delegate` and `$browser` specified): |
| | | * - passing through (delegating request to real backend) is enabled |
| | | * - auto flushing is enabled |
| | | * |
| | | * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) |
| | | * @param {Object=} $browser Auto-flushing enabled if specified |
| | | * @return {Object} Instance of $httpBackend mock |
| | | */ |
| | | function createHttpBackendMock($rootScope, $delegate, $browser) { |
| | | var definitions = [], |
| | | expectations = [], |
| | | responses = [], |
| | | responsesPush = angular.bind(responses, responses.push), |
| | | copy = angular.copy; |
| | | |
| | | function createResponse(status, data, headers, statusText) { |
| | | if (angular.isFunction(status)) return status; |
| | | |
| | | return function() { |
| | | return angular.isNumber(status) |
| | | ? [status, data, headers, statusText] |
| | | : [200, status, data]; |
| | | }; |
| | | } |
| | | |
| | | // TODO(vojta): change params to: method, url, data, headers, callback |
| | | function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) { |
| | | var xhr = new MockXhr(), |
| | | expectation = expectations[0], |
| | | wasExpected = false; |
| | | |
| | | function prettyPrint(data) { |
| | | return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) |
| | | ? data |
| | | : angular.toJson(data); |
| | | } |
| | | |
| | | function wrapResponse(wrapped) { |
| | | if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); |
| | | |
| | | return handleResponse; |
| | | |
| | | function handleResponse() { |
| | | var response = wrapped.response(method, url, data, headers); |
| | | xhr.$$respHeaders = response[2]; |
| | | callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(), |
| | | copy(response[3] || '')); |
| | | } |
| | | |
| | | function handleTimeout() { |
| | | for (var i = 0, ii = responses.length; i < ii; i++) { |
| | | if (responses[i] === handleResponse) { |
| | | responses.splice(i, 1); |
| | | callback(-1, undefined, ''); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (expectation && expectation.match(method, url)) { |
| | | if (!expectation.matchData(data)) |
| | | throw new Error('Expected ' + expectation + ' with different data\n' + |
| | | 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); |
| | | |
| | | if (!expectation.matchHeaders(headers)) |
| | | throw new Error('Expected ' + expectation + ' with different headers\n' + |
| | | 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + |
| | | prettyPrint(headers)); |
| | | |
| | | expectations.shift(); |
| | | |
| | | if (expectation.response) { |
| | | responses.push(wrapResponse(expectation)); |
| | | return; |
| | | } |
| | | wasExpected = true; |
| | | } |
| | | |
| | | var i = -1, definition; |
| | | while ((definition = definitions[++i])) { |
| | | if (definition.match(method, url, data, headers || {})) { |
| | | if (definition.response) { |
| | | // if $browser specified, we do auto flush all requests |
| | | ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); |
| | | } else if (definition.passThrough) { |
| | | $delegate(method, url, data, callback, headers, timeout, withCredentials); |
| | | } else throw new Error('No response defined !'); |
| | | return; |
| | | } |
| | | } |
| | | throw wasExpected ? |
| | | new Error('No response defined !') : |
| | | new Error('Unexpected request: ' + method + ' ' + url + '\n' + |
| | | (expectation ? 'Expected ' + expectation : 'No more request expected')); |
| | | } |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#when |
| | | * @description |
| | | * Creates a new backend definition. |
| | | * |
| | | * @param {string} method HTTP method. |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives |
| | | * data string and returns true if the data is as expected. |
| | | * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header |
| | | * object and returns true if the headers match the current definition. |
| | | * @returns {requestHandler} Returns an object with `respond` method that controls how a matched |
| | | * request is handled. |
| | | * |
| | | * - respond – |
| | | * `{function([status,] data[, headers, statusText]) |
| | | * | function(function(method, url, data, headers)}` |
| | | * – The respond method takes a set of static data to be returned or a function that can |
| | | * return an array containing response status (number), response data (string), response |
| | | * headers (Object), and the text for the status (string). |
| | | */ |
| | | $httpBackend.when = function(method, url, data, headers) { |
| | | var definition = new MockHttpExpectation(method, url, data, headers), |
| | | chain = { |
| | | respond: function(status, data, headers, statusText) { |
| | | definition.response = createResponse(status, data, headers, statusText); |
| | | } |
| | | }; |
| | | |
| | | if ($browser) { |
| | | chain.passThrough = function() { |
| | | definition.passThrough = true; |
| | | }; |
| | | } |
| | | |
| | | definitions.push(definition); |
| | | return chain; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenGET |
| | | * @description |
| | | * Creates a new backend definition for GET requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenHEAD |
| | | * @description |
| | | * Creates a new backend definition for HEAD requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenDELETE |
| | | * @description |
| | | * Creates a new backend definition for DELETE requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenPOST |
| | | * @description |
| | | * Creates a new backend definition for POST requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives |
| | | * data string and returns true if the data is as expected. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenPUT |
| | | * @description |
| | | * Creates a new backend definition for PUT requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives |
| | | * data string and returns true if the data is as expected. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenJSONP |
| | | * @description |
| | | * Creates a new backend definition for JSONP requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | createShortMethods('when'); |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expect |
| | | * @description |
| | | * Creates a new request expectation. |
| | | * |
| | | * @param {string} method HTTP method. |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that |
| | | * receives data string and returns true if the data is as expected, or Object if request body |
| | | * is in JSON format. |
| | | * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header |
| | | * object and returns true if the headers match the current expectation. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | * |
| | | * - respond – |
| | | * `{function([status,] data[, headers, statusText]) |
| | | * | function(function(method, url, data, headers)}` |
| | | * – The respond method takes a set of static data to be returned or a function that can |
| | | * return an array containing response status (number), response data (string), response |
| | | * headers (Object), and the text for the status (string). |
| | | */ |
| | | $httpBackend.expect = function(method, url, data, headers) { |
| | | var expectation = new MockHttpExpectation(method, url, data, headers); |
| | | expectations.push(expectation); |
| | | return { |
| | | respond: function (status, data, headers, statusText) { |
| | | expectation.response = createResponse(status, data, headers, statusText); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectGET |
| | | * @description |
| | | * Creates a new request expectation for GET requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. See #expect for more info. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectHEAD |
| | | * @description |
| | | * Creates a new request expectation for HEAD requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectDELETE |
| | | * @description |
| | | * Creates a new request expectation for DELETE requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectPOST |
| | | * @description |
| | | * Creates a new request expectation for POST requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that |
| | | * receives data string and returns true if the data is as expected, or Object if request body |
| | | * is in JSON format. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectPUT |
| | | * @description |
| | | * Creates a new request expectation for PUT requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that |
| | | * receives data string and returns true if the data is as expected, or Object if request body |
| | | * is in JSON format. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectPATCH |
| | | * @description |
| | | * Creates a new request expectation for PATCH requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that |
| | | * receives data string and returns true if the data is as expected, or Object if request body |
| | | * is in JSON format. |
| | | * @param {Object=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#expectJSONP |
| | | * @description |
| | | * Creates a new request expectation for JSONP requests. For more info see `expect()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @returns {requestHandler} Returns an object with `respond` method that control how a matched |
| | | * request is handled. |
| | | */ |
| | | createShortMethods('expect'); |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#flush |
| | | * @description |
| | | * Flushes all pending requests using the trained responses. |
| | | * |
| | | * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, |
| | | * all pending requests will be flushed. If there are no pending requests when the flush method |
| | | * is called an exception is thrown (as this typically a sign of programming error). |
| | | */ |
| | | $httpBackend.flush = function(count) { |
| | | $rootScope.$digest(); |
| | | if (!responses.length) throw new Error('No pending request to flush !'); |
| | | |
| | | if (angular.isDefined(count)) { |
| | | while (count--) { |
| | | if (!responses.length) throw new Error('No more pending request to flush !'); |
| | | responses.shift()(); |
| | | } |
| | | } else { |
| | | while (responses.length) { |
| | | responses.shift()(); |
| | | } |
| | | } |
| | | $httpBackend.verifyNoOutstandingExpectation(); |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#verifyNoOutstandingExpectation |
| | | * @description |
| | | * Verifies that all of the requests defined via the `expect` api were made. If any of the |
| | | * requests were not made, verifyNoOutstandingExpectation throws an exception. |
| | | * |
| | | * Typically, you would call this method following each test case that asserts requests using an |
| | | * "afterEach" clause. |
| | | * |
| | | * ```js |
| | | * afterEach($httpBackend.verifyNoOutstandingExpectation); |
| | | * ``` |
| | | */ |
| | | $httpBackend.verifyNoOutstandingExpectation = function() { |
| | | $rootScope.$digest(); |
| | | if (expectations.length) { |
| | | throw new Error('Unsatisfied requests: ' + expectations.join(', ')); |
| | | } |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#verifyNoOutstandingRequest |
| | | * @description |
| | | * Verifies that there are no outstanding requests that need to be flushed. |
| | | * |
| | | * Typically, you would call this method following each test case that asserts requests using an |
| | | * "afterEach" clause. |
| | | * |
| | | * ```js |
| | | * afterEach($httpBackend.verifyNoOutstandingRequest); |
| | | * ``` |
| | | */ |
| | | $httpBackend.verifyNoOutstandingRequest = function() { |
| | | if (responses.length) { |
| | | throw new Error('Unflushed requests: ' + responses.length); |
| | | } |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#resetExpectations |
| | | * @description |
| | | * Resets all request expectations, but preserves all backend definitions. Typically, you would |
| | | * call resetExpectations during a multiple-phase test when you want to reuse the same instance of |
| | | * $httpBackend mock. |
| | | */ |
| | | $httpBackend.resetExpectations = function() { |
| | | expectations.length = 0; |
| | | responses.length = 0; |
| | | }; |
| | | |
| | | return $httpBackend; |
| | | |
| | | |
| | | function createShortMethods(prefix) { |
| | | angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { |
| | | $httpBackend[prefix + method] = function(url, headers) { |
| | | return $httpBackend[prefix](method, url, undefined, headers); |
| | | }; |
| | | }); |
| | | |
| | | angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { |
| | | $httpBackend[prefix + method] = function(url, data, headers) { |
| | | return $httpBackend[prefix](method, url, data, headers); |
| | | }; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | function MockHttpExpectation(method, url, data, headers) { |
| | | |
| | | this.data = data; |
| | | this.headers = headers; |
| | | |
| | | this.match = function(m, u, d, h) { |
| | | if (method != m) return false; |
| | | if (!this.matchUrl(u)) return false; |
| | | if (angular.isDefined(d) && !this.matchData(d)) return false; |
| | | if (angular.isDefined(h) && !this.matchHeaders(h)) return false; |
| | | return true; |
| | | }; |
| | | |
| | | this.matchUrl = function(u) { |
| | | if (!url) return true; |
| | | if (angular.isFunction(url.test)) return url.test(u); |
| | | return url == u; |
| | | }; |
| | | |
| | | this.matchHeaders = function(h) { |
| | | if (angular.isUndefined(headers)) return true; |
| | | if (angular.isFunction(headers)) return headers(h); |
| | | return angular.equals(headers, h); |
| | | }; |
| | | |
| | | this.matchData = function(d) { |
| | | if (angular.isUndefined(data)) return true; |
| | | if (data && angular.isFunction(data.test)) return data.test(d); |
| | | if (data && angular.isFunction(data)) return data(d); |
| | | if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); |
| | | return data == d; |
| | | }; |
| | | |
| | | this.toString = function() { |
| | | return method + ' ' + url; |
| | | }; |
| | | } |
| | | |
| | | function createMockXhr() { |
| | | return new MockXhr(); |
| | | } |
| | | |
| | | function MockXhr() { |
| | | |
| | | // hack for testing $http, $httpBackend |
| | | MockXhr.$$lastInstance = this; |
| | | |
| | | this.open = function(method, url, async) { |
| | | this.$$method = method; |
| | | this.$$url = url; |
| | | this.$$async = async; |
| | | this.$$reqHeaders = {}; |
| | | this.$$respHeaders = {}; |
| | | }; |
| | | |
| | | this.send = function(data) { |
| | | this.$$data = data; |
| | | }; |
| | | |
| | | this.setRequestHeader = function(key, value) { |
| | | this.$$reqHeaders[key] = value; |
| | | }; |
| | | |
| | | this.getResponseHeader = function(name) { |
| | | // the lookup must be case insensitive, |
| | | // that's why we try two quick lookups first and full scan last |
| | | var header = this.$$respHeaders[name]; |
| | | if (header) return header; |
| | | |
| | | name = angular.lowercase(name); |
| | | header = this.$$respHeaders[name]; |
| | | if (header) return header; |
| | | |
| | | header = undefined; |
| | | angular.forEach(this.$$respHeaders, function(headerVal, headerName) { |
| | | if (!header && angular.lowercase(headerName) == name) header = headerVal; |
| | | }); |
| | | return header; |
| | | }; |
| | | |
| | | this.getAllResponseHeaders = function() { |
| | | var lines = []; |
| | | |
| | | angular.forEach(this.$$respHeaders, function(value, key) { |
| | | lines.push(key + ': ' + value); |
| | | }); |
| | | return lines.join('\n'); |
| | | }; |
| | | |
| | | this.abort = angular.noop; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $timeout |
| | | * @description |
| | | * |
| | | * This service is just a simple decorator for {@link ng.$timeout $timeout} service |
| | | * that adds a "flush" and "verifyNoPendingTasks" methods. |
| | | */ |
| | | |
| | | angular.mock.$TimeoutDecorator = function($delegate, $browser) { |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $timeout#flush |
| | | * @description |
| | | * |
| | | * Flushes the queue of pending tasks. |
| | | * |
| | | * @param {number=} delay maximum timeout amount to flush up until |
| | | */ |
| | | $delegate.flush = function(delay) { |
| | | $browser.defer.flush(delay); |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $timeout#verifyNoPendingTasks |
| | | * @description |
| | | * |
| | | * Verifies that there are no pending tasks that need to be flushed. |
| | | */ |
| | | $delegate.verifyNoPendingTasks = function() { |
| | | if ($browser.deferredFns.length) { |
| | | throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + |
| | | formatPendingTasksAsString($browser.deferredFns)); |
| | | } |
| | | }; |
| | | |
| | | function formatPendingTasksAsString(tasks) { |
| | | var result = []; |
| | | angular.forEach(tasks, function(task) { |
| | | result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); |
| | | }); |
| | | |
| | | return result.join(', '); |
| | | } |
| | | |
| | | return $delegate; |
| | | }; |
| | | |
| | | angular.mock.$RAFDecorator = function($delegate) { |
| | | var queue = []; |
| | | var rafFn = function(fn) { |
| | | var index = queue.length; |
| | | queue.push(fn); |
| | | return function() { |
| | | queue.splice(index, 1); |
| | | }; |
| | | }; |
| | | |
| | | rafFn.supported = $delegate.supported; |
| | | |
| | | rafFn.flush = function() { |
| | | if(queue.length === 0) { |
| | | throw new Error('No rAF callbacks present'); |
| | | } |
| | | |
| | | var length = queue.length; |
| | | for(var i=0;i<length;i++) { |
| | | queue[i](); |
| | | } |
| | | |
| | | queue = []; |
| | | }; |
| | | |
| | | return rafFn; |
| | | }; |
| | | |
| | | angular.mock.$AsyncCallbackDecorator = function($delegate) { |
| | | var callbacks = []; |
| | | var addFn = function(fn) { |
| | | callbacks.push(fn); |
| | | }; |
| | | addFn.flush = function() { |
| | | angular.forEach(callbacks, function(fn) { |
| | | fn(); |
| | | }); |
| | | callbacks = []; |
| | | }; |
| | | return addFn; |
| | | }; |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | angular.mock.$RootElementProvider = function() { |
| | | this.$get = function() { |
| | | return angular.element('<div ng-app></div>'); |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc module |
| | | * @name ngMock |
| | | * @description |
| | | * |
| | | * # ngMock |
| | | * |
| | | * The `ngMock` module providers support to inject and mock Angular services into unit tests. |
| | | * In addition, ngMock also extends various core ng services such that they can be |
| | | * inspected and controlled in a synchronous manner within test code. |
| | | * |
| | | * |
| | | * <div doc-module-components="ngMock"></div> |
| | | * |
| | | */ |
| | | angular.module('ngMock', ['ng']).provider({ |
| | | $browser: angular.mock.$BrowserProvider, |
| | | $exceptionHandler: angular.mock.$ExceptionHandlerProvider, |
| | | $log: angular.mock.$LogProvider, |
| | | $interval: angular.mock.$IntervalProvider, |
| | | $httpBackend: angular.mock.$HttpBackendProvider, |
| | | $rootElement: angular.mock.$RootElementProvider |
| | | }).config(['$provide', function($provide) { |
| | | $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); |
| | | $provide.decorator('$$rAF', angular.mock.$RAFDecorator); |
| | | $provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator); |
| | | }]); |
| | | |
| | | /** |
| | | * @ngdoc module |
| | | * @name ngMockE2E |
| | | * @module ngMockE2E |
| | | * @description |
| | | * |
| | | * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. |
| | | * Currently there is only one mock present in this module - |
| | | * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. |
| | | */ |
| | | angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { |
| | | $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); |
| | | }]); |
| | | |
| | | /** |
| | | * @ngdoc service |
| | | * @name $httpBackend |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of |
| | | * applications that use the {@link ng.$http $http service}. |
| | | * |
| | | * *Note*: For fake http backend implementation suitable for unit testing please see |
| | | * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. |
| | | * |
| | | * This implementation can be used to respond with static or dynamic responses via the `when` api |
| | | * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the |
| | | * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch |
| | | * templates from a webserver). |
| | | * |
| | | * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application |
| | | * is being developed with the real backend api replaced with a mock, it is often desirable for |
| | | * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch |
| | | * templates or static files from the webserver). To configure the backend with this behavior |
| | | * use the `passThrough` request handler of `when` instead of `respond`. |
| | | * |
| | | * Additionally, we don't want to manually have to flush mocked out requests like we do during unit |
| | | * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests |
| | | * automatically, closely simulating the behavior of the XMLHttpRequest object. |
| | | * |
| | | * To setup the application to run with this http backend, you have to create a module that depends |
| | | * on the `ngMockE2E` and your application modules and defines the fake backend: |
| | | * |
| | | * ```js |
| | | * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']); |
| | | * myAppDev.run(function($httpBackend) { |
| | | * phones = [{name: 'phone1'}, {name: 'phone2'}]; |
| | | * |
| | | * // returns the current list of phones |
| | | * $httpBackend.whenGET('/phones').respond(phones); |
| | | * |
| | | * // adds a new phone to the phones array |
| | | * $httpBackend.whenPOST('/phones').respond(function(method, url, data) { |
| | | * var phone = angular.fromJson(data); |
| | | * phones.push(phone); |
| | | * return [200, phone, {}]; |
| | | * }); |
| | | * $httpBackend.whenGET(/^\/templates\//).passThrough(); |
| | | * //... |
| | | * }); |
| | | * ``` |
| | | * |
| | | * Afterwards, bootstrap your app with this new module. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#when |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition. |
| | | * |
| | | * @param {string} method HTTP method. |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp)=} data HTTP request body. |
| | | * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header |
| | | * object and returns true if the headers match the current definition. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | * |
| | | * - respond – |
| | | * `{function([status,] data[, headers, statusText]) |
| | | * | function(function(method, url, data, headers)}` |
| | | * – The respond method takes a set of static data to be returned or a function that can return |
| | | * an array containing response status (number), response data (string), response headers |
| | | * (Object), and the text for the status (string). |
| | | * - passThrough – `{function()}` – Any request matching a backend definition with |
| | | * `passThrough` handler will be passed through to the real backend (an XHR request will be made |
| | | * to the server.) |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenGET |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for GET requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenHEAD |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for HEAD requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenDELETE |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for DELETE requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenPOST |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for POST requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp)=} data HTTP request body. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenPUT |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for PUT requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp)=} data HTTP request body. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenPATCH |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for PATCH requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @param {(string|RegExp)=} data HTTP request body. |
| | | * @param {(Object|function(Object))=} headers HTTP headers. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | |
| | | /** |
| | | * @ngdoc method |
| | | * @name $httpBackend#whenJSONP |
| | | * @module ngMockE2E |
| | | * @description |
| | | * Creates a new backend definition for JSONP requests. For more info see `when()`. |
| | | * |
| | | * @param {string|RegExp} url HTTP url. |
| | | * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that |
| | | * control how a matched request is handled. |
| | | */ |
| | | angular.mock.e2e = {}; |
| | | angular.mock.e2e.$httpBackendDecorator = |
| | | ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; |
| | | |
| | | |
| | | angular.mock.clearDataCache = function() { |
| | | var key, |
| | | cache = angular.element.cache; |
| | | |
| | | for(key in cache) { |
| | | if (Object.prototype.hasOwnProperty.call(cache,key)) { |
| | | var handle = cache[key].handle; |
| | | |
| | | handle && angular.element(handle.elem).off(); |
| | | delete cache[key]; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | |
| | | if(window.jasmine || window.mocha) { |
| | | |
| | | var currentSpec = null, |
| | | isSpecRunning = function() { |
| | | return !!currentSpec; |
| | | }; |
| | | |
| | | |
| | | (window.beforeEach || window.setup)(function() { |
| | | currentSpec = this; |
| | | }); |
| | | |
| | | (window.afterEach || window.teardown)(function() { |
| | | var injector = currentSpec.$injector; |
| | | |
| | | currentSpec.$injector = null; |
| | | currentSpec.$modules = null; |
| | | currentSpec = null; |
| | | |
| | | if (injector) { |
| | | injector.get('$rootElement').off(); |
| | | injector.get('$browser').pollFns.length = 0; |
| | | } |
| | | |
| | | angular.mock.clearDataCache(); |
| | | |
| | | // clean up jquery's fragment cache |
| | | angular.forEach(angular.element.fragments, function(val, key) { |
| | | delete angular.element.fragments[key]; |
| | | }); |
| | | |
| | | MockXhr.$$lastInstance = null; |
| | | |
| | | angular.forEach(angular.callbacks, function(val, key) { |
| | | delete angular.callbacks[key]; |
| | | }); |
| | | angular.callbacks.counter = 0; |
| | | }); |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name angular.mock.module |
| | | * @description |
| | | * |
| | | * *NOTE*: This function is also published on window for easy access.<br> |
| | | * |
| | | * This function registers a module configuration code. It collects the configuration information |
| | | * which will be used when the injector is created by {@link angular.mock.inject inject}. |
| | | * |
| | | * See {@link angular.mock.inject inject} for usage example |
| | | * |
| | | * @param {...(string|Function|Object)} fns any number of modules which are represented as string |
| | | * aliases or as anonymous module initialization functions. The modules are used to |
| | | * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an |
| | | * object literal is passed they will be registered as values in the module, the key being |
| | | * the module name and the value being what is returned. |
| | | */ |
| | | window.module = angular.mock.module = function() { |
| | | var moduleFns = Array.prototype.slice.call(arguments, 0); |
| | | return isSpecRunning() ? workFn() : workFn; |
| | | ///////////////////// |
| | | function workFn() { |
| | | if (currentSpec.$injector) { |
| | | throw new Error('Injector already created, can not register a module!'); |
| | | } else { |
| | | var modules = currentSpec.$modules || (currentSpec.$modules = []); |
| | | angular.forEach(moduleFns, function(module) { |
| | | if (angular.isObject(module) && !angular.isArray(module)) { |
| | | modules.push(function($provide) { |
| | | angular.forEach(module, function(value, key) { |
| | | $provide.value(key, value); |
| | | }); |
| | | }); |
| | | } else { |
| | | modules.push(module); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * @ngdoc function |
| | | * @name angular.mock.inject |
| | | * @description |
| | | * |
| | | * *NOTE*: This function is also published on window for easy access.<br> |
| | | * |
| | | * The inject function wraps a function into an injectable function. The inject() creates new |
| | | * instance of {@link auto.$injector $injector} per test, which is then used for |
| | | * resolving references. |
| | | * |
| | | * |
| | | * ## Resolving References (Underscore Wrapping) |
| | | * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this |
| | | * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable |
| | | * that is declared in the scope of the `describe()` block. Since we would, most likely, want |
| | | * the variable to have the same name of the reference we have a problem, since the parameter |
| | | * to the `inject()` function would hide the outer variable. |
| | | * |
| | | * To help with this, the injected parameters can, optionally, be enclosed with underscores. |
| | | * These are ignored by the injector when the reference name is resolved. |
| | | * |
| | | * For example, the parameter `_myService_` would be resolved as the reference `myService`. |
| | | * Since it is available in the function body as _myService_, we can then assign it to a variable |
| | | * defined in an outer scope. |
| | | * |
| | | * ``` |
| | | * // Defined out reference variable outside |
| | | * var myService; |
| | | * |
| | | * // Wrap the parameter in underscores |
| | | * beforeEach( inject( function(_myService_){ |
| | | * myService = _myService_; |
| | | * })); |
| | | * |
| | | * // Use myService in a series of tests. |
| | | * it('makes use of myService', function() { |
| | | * myService.doStuff(); |
| | | * }); |
| | | * |
| | | * ``` |
| | | * |
| | | * See also {@link angular.mock.module angular.mock.module} |
| | | * |
| | | * ## Example |
| | | * Example of what a typical jasmine tests looks like with the inject method. |
| | | * ```js |
| | | * |
| | | * angular.module('myApplicationModule', []) |
| | | * .value('mode', 'app') |
| | | * .value('version', 'v1.0.1'); |
| | | * |
| | | * |
| | | * describe('MyApp', function() { |
| | | * |
| | | * // You need to load modules that you want to test, |
| | | * // it loads only the "ng" module by default. |
| | | * beforeEach(module('myApplicationModule')); |
| | | * |
| | | * |
| | | * // inject() is used to inject arguments of all given functions |
| | | * it('should provide a version', inject(function(mode, version) { |
| | | * expect(version).toEqual('v1.0.1'); |
| | | * expect(mode).toEqual('app'); |
| | | * })); |
| | | * |
| | | * |
| | | * // The inject and module method can also be used inside of the it or beforeEach |
| | | * it('should override a version and test the new version is injected', function() { |
| | | * // module() takes functions or strings (module aliases) |
| | | * module(function($provide) { |
| | | * $provide.value('version', 'overridden'); // override version here |
| | | * }); |
| | | * |
| | | * inject(function(version) { |
| | | * expect(version).toEqual('overridden'); |
| | | * }); |
| | | * }); |
| | | * }); |
| | | * |
| | | * ``` |
| | | * |
| | | * @param {...Function} fns any number of functions which will be injected using the injector. |
| | | */ |
| | | |
| | | |
| | | |
| | | var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { |
| | | this.message = e.message; |
| | | this.name = e.name; |
| | | if (e.line) this.line = e.line; |
| | | if (e.sourceId) this.sourceId = e.sourceId; |
| | | if (e.stack && errorForStack) |
| | | this.stack = e.stack + '\n' + errorForStack.stack; |
| | | if (e.stackArray) this.stackArray = e.stackArray; |
| | | }; |
| | | ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; |
| | | |
| | | window.inject = angular.mock.inject = function() { |
| | | var blockFns = Array.prototype.slice.call(arguments, 0); |
| | | var errorForStack = new Error('Declaration Location'); |
| | | return isSpecRunning() ? workFn.call(currentSpec) : workFn; |
| | | ///////////////////// |
| | | function workFn() { |
| | | var modules = currentSpec.$modules || []; |
| | | |
| | | modules.unshift('ngMock'); |
| | | modules.unshift('ng'); |
| | | var injector = currentSpec.$injector; |
| | | if (!injector) { |
| | | injector = currentSpec.$injector = angular.injector(modules); |
| | | } |
| | | for(var i = 0, ii = blockFns.length; i < ii; i++) { |
| | | try { |
| | | /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ |
| | | injector.invoke(blockFns[i] || angular.noop, this); |
| | | /* jshint +W040 */ |
| | | } catch (e) { |
| | | if (e.stack && errorForStack) { |
| | | throw new ErrorAddingDeclarationLocationStack(e, errorForStack); |
| | | } |
| | | throw e; |
| | | } finally { |
| | | errorForStack = null; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | |
| | | })(window, window.angular); |
todo-angular/src/assets/js/libs/angular/angular-resource.js
todo-angular/src/assets/js/libs/angular/angular-resource.min.js
todo-angular/src/assets/js/libs/angular/angular-resource.min.js.map
todo-angular/src/assets/js/libs/angular/angular-route.js
todo-angular/src/assets/js/libs/angular/angular-route.min.js
todo-angular/src/assets/js/libs/angular/angular-route.min.js.map
todo-angular/src/assets/js/libs/angular/angular-sanitize.js
todo-angular/src/assets/js/libs/angular/angular-sanitize.min.js
todo-angular/src/assets/js/libs/angular/angular-sanitize.min.js.map
todo-angular/src/assets/js/libs/angular/angular-scenario.js
todo-angular/src/assets/js/libs/angular/angular-touch.js
todo-angular/src/assets/js/libs/angular/angular-touch.min.js
todo-angular/src/assets/js/libs/angular/angular-touch.min.js.map
todo-angular/src/assets/js/libs/angular/angular.js
todo-angular/src/assets/js/libs/angular/angular.min.js
todo-angular/src/assets/js/libs/angular/angular.min.js.map
todo-angular/src/assets/js/libs/bootstrap/bootstrap.js
todo-angular/src/assets/js/libs/bootstrap/bootstrap.min.js
todo-angular/src/assets/js/libs/jquery/jquery-1.11.1.min.js
todo-angular/src/assets/js/libs/jquery/jquery-1.11.1.min.map
todo-angular/src/assets/partials/create.html
todo-angular/src/assets/partials/edit.html
todo-angular/src/assets/partials/list.html
todo-angular/src/index.html |